diff --git a/README.md b/README.md deleted file mode 100644 index ea46267..0000000 --- a/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Codigo para llevar's generator - -This is the static site generator used to build [Codigo Para Llevar](https://codigoparallevar.com/) (my personal site). It contains: - -- A markdown blog (with content ported from acrylamid). Saved as `/blog/`. -- A set of org-mode based notes. Saved as `/notes/`. - -It also copies over some static assets (css, js, fonts). - -The scripts are hardcoded with the hostnames and paths for my own site, so you might want to update them. - -General documentation is in progress and might be replaced little by little by the more interactive [org-web-editor](https://code.codigoparallevar.com/kenkeiras/org-web-editor) once that one (1) supports all the features here and (2) has support for building static sites. - -## Instructions - -Generally, what you want to do is to run `make` once to prepare the static files, then run this to generate the notes. - -```bash -mkdir -p _gen -WATCH_AND_REBUILD=0 python3 scripts/generate.py _gen/notes [] -``` - -Use `WATCH_AND_REBUILD=1` (or empty) for automatic rebuilds. - -## Filtering - -This won't render **all** notes, but try to select the PUBLIC ones and skip the PRIVATE ones. - -PUBLIC files are contained on the DEFAULT_SUBPATH, PRIVATE headlines have the `:private:` tag. diff --git a/scripts/blog.py b/scripts/blog.py index d177201..d2d6d83 100644 --- a/scripts/blog.py +++ b/scripts/blog.py @@ -22,6 +22,7 @@ import shutil import traceback import time import re +import sqlite3 from typing import List from bs4 import BeautifulSoup as bs4 @@ -63,6 +64,7 @@ JINJA_ENV = jinja2.Environment( autoescape=jinja2.select_autoescape() ) +PARSER_NAMESPACE = 'codigoparallevar.com/blog' WATCH = True if os.getenv('WATCH_AND_REBUILD', '1') == '0': WATCH = False @@ -176,6 +178,12 @@ def get_out_path(front_matter): return out_path +def create_db(path): + db = sqlite3.connect(path) + db.execute('CREATE VIRTUAL TABLE IF NOT EXISTS note_search USING fts5(note_id, title, body, top_level_title, is_done, is_todo, parser_namespace, url, tokenize="trigram");') + db.execute('DELETE FROM note_search WHERE parser_namespace = ?;', (PARSER_NAMESPACE,)) + return db + def load_all(top_dir_relative): top = os.path.abspath(top_dir_relative) @@ -456,10 +464,39 @@ def render_rss(docs, dest_top): f.write(result) -def regen_all(source_top, dest_top, docs=None): +def regen_all(source_top, dest_top, docs=None, db=None): if docs is None: docs = load_all(source_top) + cur = db.cursor() + cleaned_db = False + + try: + cur.execute('DELETE FROM note_search WHERE parser_namespace = ?;', (PARSER_NAMESPACE,)) + cleaned_db = True + except sqlite3.OperationalError as err: + if WATCH: + logging.warning("Error pre-cleaning DB, search won't be updated") + else: + raise + + # Save posts to DB + for (doc, front_matter, out_path) in docs.values(): + cur.execute('''INSERT INTO note_search(note_id, title, body, top_level_title, is_done, is_todo, parser_namespace, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?);''', + ( + out_path, + front_matter['title'], + doc, + front_matter['title'], + False, + False, + PARSER_NAMESPACE, + out_path + '/index.html', + )) + + cur.close() + db.commit() + # Render posts for (doc, front_matter, out_path) in docs.values(): doc_full_path = os.path.join(dest_top, out_path) @@ -513,7 +550,8 @@ def main(source_top, dest_top): ## Initial load t0 = time.time() logging.info("Initial load...") - docs = regen_all(source_top, dest_top) + db = create_db(os.path.join(dest_top, '..', 'db.sqlite3')) + docs = regen_all(source_top, dest_top, db=db) logging.info("Initial load completed in {:.2f}s".format(time.time() - t0)) if not WATCH: @@ -557,7 +595,7 @@ def main(source_top, dest_top): if is_static_resource: logging.info("Updated static resources in {:.2f}s".format(time.time() - t0)) else: - docs = regen_all(source_top, dest_top, docs) + docs = regen_all(source_top, dest_top, docs, db=db) logging.info("Updated all in {:.2f}s".format(time.time() - t0)) else: diff --git a/scripts/generate.py b/scripts/generate.py index 12bac97..4ceaf8c 100644 --- a/scripts/generate.py +++ b/scripts/generate.py @@ -46,14 +46,14 @@ IMG_EXTENSIONS = set([ "gif", ]) SKIPPED_TAGS = set(['attach']) -DEFAULT_SUBPATH = "public" +PARSER_NAMESPACE = 'codigoparallevar.com/notes' WATCH = True if os.getenv('WATCH_AND_REBUILD', '1') == '0': WATCH = False MIN_HIDDEN_HEADLINE_LEVEL = 2 -INDEX_ID = os.getenv("INDEX_ID", "ea48ec1d-f9d4-4fb7-b39a-faa7b6e2ba95") +INDEX_ID = "ea48ec1d-f9d4-4fb7-b39a-faa7b6e2ba95" SITE_NAME = "Código para llevar" MONITORED_EVENT_TYPES = ( @@ -89,11 +89,9 @@ def is_git_path(path): return any([chunk == ".git" for chunk in path.split(os.sep)]) def create_db(path): - if os.path.exists(path): - os.unlink(path) - db = sqlite3.connect(path) - db.execute('CREATE VIRTUAL TABLE note_search USING fts5(note_id, title, body, top_level_title, is_done, is_todo, tokenize="trigram");') + db.execute('CREATE VIRTUAL TABLE IF NOT EXISTS note_search USING fts5(note_id, title, body, top_level_title, is_done, is_todo, parser_namespace, url tokenize="trigram");') + db.execute('DELETE FROM note_search WHERE parser_namespace = ?;', (PARSER_NAMESPACE,)) return db def load_all(top_dir_relative): @@ -109,9 +107,7 @@ def load_all(top_dir_relative): path = os.path.join(root, name) try: - doc = load_org(open(path), - environment={"org-todo-keywords": "TODO(t) NEXT(n) MEETING(m/!) Q(q) PAUSED(p!/!) EVENT(e/!) SOMETIME(s) WAITING(w@/!) TRACK(r/!) | DISCARDED(x@/!) VALIDATING(v!/!) DONE(d!/!)"}, - extra_cautious=True) + doc = load_org(open(path), extra_cautious=True) docs.append(doc) except Exception as err: import traceback @@ -123,28 +119,13 @@ def load_all(top_dir_relative): logging.info("Collected {} files".format(len(docs))) return docs -def remove_non_public_headlines(doc: org_rw.OrgDoc | org_rw.Headline): - if isinstance(doc, org_rw.OrgDoc): - doc.headlines = list(filter_private_headlines(doc.headlines)) - for hl in doc.headlines: - remove_non_public_headlines(hl) - else: - doc.children = list(filter_private_headlines(doc.children)) - for hl in doc.children: - remove_non_public_headlines(hl) - -def filter_private_headlines(headlines): - for hl in headlines: - if 'private' not in hl.tags: - yield hl - -def regen_all(src_top, dest_top, subpath, *, docs=None, db=None): +def regen_all(src_top, dest_top, *, docs=None, db=None): files_generated = 0 cur = db.cursor() cleaned_db = False try: - cur.execute('DELETE FROM note_search;') + cur.execute('DELETE FROM note_search WHERE parser_namespace = ?;', (PARSER_NAMESPACE,)) cleaned_db = True except sqlite3.OperationalError as err: if WATCH: @@ -165,12 +146,10 @@ def regen_all(src_top, dest_top, subpath, *, docs=None, db=None): main_headline_to_docid = {} for doc in docs: relpath = os.path.relpath(doc.path, src_top) - - remove_non_public_headlines(doc) changed = False headlines = list(doc.getAllHeadlines()) related = None - if not relpath.startswith(subpath + "/"): + if not relpath.startswith("public/"): # print("Skip:", relpath) continue @@ -282,7 +261,7 @@ def regen_all(src_top, dest_top, subpath, *, docs=None, db=None): topLevelHeadline = topLevelHeadline.parent # Save for full-text-search - cur.execute('''INSERT INTO note_search(note_id, title, body, top_level_title, is_done, is_todo) VALUES (?, ?, ?, ?, ?, ?);''', + cur.execute('''INSERT INTO note_search(note_id, title, body, top_level_title, is_done, is_todo, parser_namespace, url) VALUES (?, ?, ?, ?, ?, ?, ?, ?);''', ( headline.id, headline.title.get_text(), @@ -290,6 +269,8 @@ def regen_all(src_top, dest_top, subpath, *, docs=None, db=None): topLevelHeadline.title.get_text(), headline.is_done, headline.is_todo, + PARSER_NAMESPACE, + headline.id + '.node.html', )) # Update graph, replace document ids with headline ids @@ -369,15 +350,15 @@ def regen_all(src_top, dest_top, subpath, *, docs=None, db=None): dirs_exist_ok=True) -def main(src_top, dest_top, subpath): +def main(src_top, dest_top): notifier = inotify.adapters.InotifyTrees([src_top, STATIC_PATH]) ## Initial load t0 = time.time() os.makedirs(dest_top, exist_ok=True) - db = create_db(os.path.join(dest_top, 'db.sqlite3')) - docs = regen_all(src_top, dest_top, subpath=subpath, db=db) + db = create_db(os.path.join(dest_top, '..', 'db.sqlite3')) + docs = regen_all(src_top, dest_top, db=db) if not WATCH: logging.info("Build completed in {:.2f}s".format(time.time() - t0)) @@ -395,7 +376,7 @@ def main(src_top, dest_top, subpath): print("CHANGED: {}".format(filepath)) t0 = time.time() try: - docs = regen_all(src_top, dest_top, subpath=subpath, docs=docs, db=db) + docs = regen_all(src_top, dest_top, docs=docs, db=db) except: logging.error(traceback.format_exc()) logging.error("Loading new templates failed 😿") @@ -497,7 +478,7 @@ def unindent(content): len(l) - len(l.lstrip(' ')) for l in content.split('\n') if len(l.strip()) > 0 - ] or [0]) + ]) content_lines = [ l[base_indentation:] for l in content.split('\n') @@ -530,12 +511,6 @@ def render_results_block(element, acc, headline, graph): if len(content.strip()) > 0: render_block(content, acc, _class='results lang-text', is_code=False) -def render_generic_drawer_block(element, acc, headline, graph): - items = [e.get_raw() for e in element.children] - content = '\n'.join(items) - if len(content.strip()) > 0: - render_block(content, acc, _class='generic-drawer {}-drawer lang-text'.format(element.drawer_name), is_code=False) - def render_org_text(element, acc, headline, graph): as_dom = org_rw.text_to_dom(element.contents, element) render_text_tokens(as_dom, acc, headline, graph) @@ -668,7 +643,6 @@ def render_tag(element, acc, headline, graph): dom.CodeBlock: render_code_block, dom.Text: render_text, dom.ResultsDrawerNode: render_results_block, - dom.GenericDrawerNode: render_generic_drawer_block, org_rw.Text: render_org_text, }[type(element)](element, acc, headline, graph) @@ -741,11 +715,8 @@ def render_connections(headline_id, content, graph, doc_to_headline_remapping): # return logging.info("Generating centered graph for {}".format(headline_id)) - try: - svg = gen_centered_graph.gen(headline_id, graph['nodes'], doc_to_headline_remapping) - content.append("
{}
".format(svg)) - except: - logging.warning("Broken reference on headline ID={}".format(headline_id)) + svg = gen_centered_graph.gen(headline_id, graph['nodes'], doc_to_headline_remapping) + content.append("
{}
".format(svg)) def render(headline, doc, graph, headlineLevel, doc_to_headline_remapping): try: @@ -765,10 +736,10 @@ def render(headline, doc, graph, headlineLevel, doc_to_headline_remapping): content.append(render(child, doc, headlineLevel=headlineLevel+1, graph=graph, doc_to_headline_remapping=doc_to_headline_remapping)) - if headline.state is None or headline.state.get('name') is None: + if headline.state is None: state = "" else: - state = f'{headline.state["name"]}' + state = f'{headline.state}' if headline.is_todo: todo_state = "todo" @@ -855,13 +826,9 @@ def save_changes(doc): if __name__ == "__main__": - if len(sys.argv) not in (3, 4): - print("Usage: {} SOURCE_TOP DEST_TOP ".format(sys.argv[0])) + if len(sys.argv) != 3: + print("Usage: {} SOURCE_TOP DEST_TOP".format(sys.argv[0])) exit(0) logging.basicConfig(level=logging.INFO, format="%(levelname)-8s %(message)s") - subpath = DEFAULT_SUBPATH - - if len(sys.argv) == 4: - subpath = sys.argv[3] - exit(main(sys.argv[1], sys.argv[2], subpath=subpath)) + exit(main(sys.argv[1], sys.argv[2])) diff --git a/scripts/search-server.sh b/scripts/search-server.sh index 62abda0..49f0250 100644 --- a/scripts/search-server.sh +++ b/scripts/search-server.sh @@ -12,4 +12,4 @@ cd ../../_gen/notes/ set -x -exec docker run -it --rm -p $PORT:80 -e SNIPPET_SIZE=256 -e PORT=80 -e DB_PATH=/db.sqlite3 -v `pwd`/db.sqlite3:/db.sqlite3:ro search-server +exec docker run -it --rm -p $PORT:80 -e PORT=80 -e DB_PATH=/db.sqlite3 -v `pwd`/db.sqlite3:/db.sqlite3:ro search-server diff --git a/scripts/search-server/server.go b/scripts/search-server/server.go index be6ab0d..8914956 100644 --- a/scripts/search-server/server.go +++ b/scripts/search-server/server.go @@ -33,22 +33,6 @@ func main() { port = port_num } - snippet_size := 128 - snippet_size_str, ok := os.LookupEnv("SNIPPET_SIZE") - if ok { - snippet_size_num, err := strconv.Atoi(snippet_size_str) - - if err != nil { - log.Fatal(err) - os.Exit(1) - } - if (snippet_size_num < 64) { - log.Fatal("Environment variale $SNIPPET_SIZE must be >= 64.") - os.Exit(1) - } - snippet_size = snippet_size_num - } - db, err := sql.Open("sqlite3", database_path) if err != nil { log.Fatal(err) @@ -79,23 +63,8 @@ func main() { c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, OPTIONS") query := c.Query("q") - body_type := c.Query("body") - - if ((body_type != "all") && (body_type != "none") && (body_type != "snippet")) { - body_type = "none" - } - - var stm *sql.Stmt - var err error - - if (body_type == "snippet") { - stm, err = db.Prepare("SELECT note_id, highlight(note_search, 1, '', ''), top_level_title, is_done, is_todo, snippet(note_search, 2, '', '', '', ?) FROM note_search(?)") - } else if (body_type == "all") { - stm, err = db.Prepare("SELECT note_id, highlight(note_search, 1, '', ''), top_level_title, is_done, is_todo, highlight(note_search, 2, '', '') FROM note_search(?)") - } else if (body_type == "none") { - stm, err = db.Prepare("SELECT note_id, highlight(note_search, 1, '', ''), top_level_title, is_done, is_todo FROM note_search(?)") - } + stm, err := db.Prepare("SELECT note_id, title, top_level_title, is_done, is_todo FROM note_search(?)") if err != nil { log.Fatal(err) @@ -107,13 +76,8 @@ func main() { } results := make([]map[string]string, 0) - var rows *sql.Rows - if (body_type == "snippet") { - rows, err = stm.Query(snippet_size, query) - } else { - rows, err = stm.Query(query) - } + rows, err := stm.Query(query) if err != nil { log.Fatal(err) c.JSON(500, gin.H{ @@ -130,31 +94,13 @@ func main() { var note_is_done string var note_is_todo string - item := make(map[string]string) - - if (body_type != "none") { - var note_highlight string - - err = rows.Scan( - ¬e_id, - ¬e_title, - ¬e_top_level_title, - ¬e_is_done, - ¬e_is_todo, - ¬e_highlight, - ) - if (body_type != "none") { - item["highlight"] = note_highlight - } - } else { - err = rows.Scan( - ¬e_id, - ¬e_title, - ¬e_top_level_title, - ¬e_is_done, - ¬e_is_todo, - ) - } + err = rows.Scan( + ¬e_id, + ¬e_title, + ¬e_top_level_title, + ¬e_is_done, + ¬e_is_todo, + ) if err != nil { log.Fatal(err) c.JSON(500, gin.H{ @@ -164,6 +110,7 @@ func main() { return } + item := make(map[string]string) item["id"] = note_id item["title"] = note_title item["top_level_title"] = note_top_level_title diff --git a/static/dark-syntax.css b/static/dark-syntax.css index afdbd46..2938240 100644 --- a/static/dark-syntax.css +++ b/static/dark-syntax.css @@ -1,85 +1,82 @@ -/* Dark mode. */ -@media (prefers-color-scheme: dark) { - pre { line-height: 125%; } - td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } - span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } - td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } - span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } - .hll { background-color: #49483e } - .c { color: #75715e } /* Comment */ - .err { color: #960050; background-color: #1e0010 } /* Error */ - .esc { color: #f8f8f2 } /* Escape */ - .g { color: #f8f8f2 } /* Generic */ - .k { color: #66d9ef } /* Keyword */ - .l { color: #ae81ff } /* Literal */ - .n { color: #f8f8f2 } /* Name */ - .o { color: #f92672 } /* Operator */ - .x { color: #f8f8f2 } /* Other */ - .p { color: #f8f8f2 } /* Punctuation */ - .ch { color: #75715e } /* Comment.Hashbang */ - .cm { color: #75715e } /* Comment.Multiline */ - .cp { color: #75715e } /* Comment.Preproc */ - .cpf { color: #75715e } /* Comment.PreprocFile */ - .c1 { color: #75715e } /* Comment.Single */ - .cs { color: #75715e } /* Comment.Special */ - .gd { color: #f92672 } /* Generic.Deleted */ - .ge { color: #f8f8f2; font-style: italic } /* Generic.Emph */ - .gr { color: #f8f8f2 } /* Generic.Error */ - .gh { color: #f8f8f2 } /* Generic.Heading */ - .gi { color: #a6e22e } /* Generic.Inserted */ - .go { color: #66d9ef } /* Generic.Output */ - .gp { color: #f92672; font-weight: bold } /* Generic.Prompt */ - .gs { color: #f8f8f2; font-weight: bold } /* Generic.Strong */ - .gu { color: #75715e } /* Generic.Subheading */ - .gt { color: #f8f8f2 } /* Generic.Traceback */ - .kc { color: #66d9ef } /* Keyword.Constant */ - .kd { color: #66d9ef } /* Keyword.Declaration */ - .kn { color: #f92672 } /* Keyword.Namespace */ - .kp { color: #66d9ef } /* Keyword.Pseudo */ - .kr { color: #66d9ef } /* Keyword.Reserved */ - .kt { color: #66d9ef } /* Keyword.Type */ - .ld { color: #e6db74 } /* Literal.Date */ - .m { color: #ae81ff } /* Literal.Number */ - .s { color: #e6db74 } /* Literal.String */ - .na { color: #a6e22e } /* Name.Attribute */ - .nb { color: #f8f8f2 } /* Name.Builtin */ - .nc { color: #a6e22e } /* Name.Class */ - .no { color: #66d9ef } /* Name.Constant */ - .nd { color: #a6e22e } /* Name.Decorator */ - .ni { color: #f8f8f2 } /* Name.Entity */ - .ne { color: #a6e22e } /* Name.Exception */ - .nf { color: #a6e22e } /* Name.Function */ - .nl { color: #f8f8f2 } /* Name.Label */ - .nn { color: #f8f8f2 } /* Name.Namespace */ - .nx { color: #a6e22e } /* Name.Other */ - .py { color: #f8f8f2 } /* Name.Property */ - .nt { color: #f92672 } /* Name.Tag */ - .nv { color: #f8f8f2 } /* Name.Variable */ - .ow { color: #f92672 } /* Operator.Word */ - .w { color: #f8f8f2 } /* Text.Whitespace */ - .mb { color: #ae81ff } /* Literal.Number.Bin */ - .mf { color: #ae81ff } /* Literal.Number.Float */ - .mh { color: #ae81ff } /* Literal.Number.Hex */ - .mi { color: #ae81ff } /* Literal.Number.Integer */ - .mo { color: #ae81ff } /* Literal.Number.Oct */ - .sa { color: #e6db74 } /* Literal.String.Affix */ - .sb { color: #e6db74 } /* Literal.String.Backtick */ - .sc { color: #e6db74 } /* Literal.String.Char */ - .dl { color: #e6db74 } /* Literal.String.Delimiter */ - .sd { color: #e6db74 } /* Literal.String.Doc */ - .s2 { color: #e6db74 } /* Literal.String.Double */ - .se { color: #ae81ff } /* Literal.String.Escape */ - .sh { color: #e6db74 } /* Literal.String.Heredoc */ - .si { color: #e6db74 } /* Literal.String.Interpol */ - .sx { color: #e6db74 } /* Literal.String.Other */ - .sr { color: #e6db74 } /* Literal.String.Regex */ - .s1 { color: #e6db74 } /* Literal.String.Single */ - .ss { color: #e6db74 } /* Literal.String.Symbol */ - .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ - .fm { color: #a6e22e } /* Name.Function.Magic */ - .vc { color: #f8f8f2 } /* Name.Variable.Class */ - .vg { color: #f8f8f2 } /* Name.Variable.Global */ - .vi { color: #f8f8f2 } /* Name.Variable.Instance */ - .vm { color: #f8f8f2 } /* Name.Variable.Magic */ - .il { color: #ae81ff } /* Literal.Number.Integer.Long */ -} +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.hll { background-color: #49483e } +.c { color: #75715e } /* Comment */ +.err { color: #960050; background-color: #1e0010 } /* Error */ +.esc { color: #f8f8f2 } /* Escape */ +.g { color: #f8f8f2 } /* Generic */ +.k { color: #66d9ef } /* Keyword */ +.l { color: #ae81ff } /* Literal */ +.n { color: #f8f8f2 } /* Name */ +.o { color: #f92672 } /* Operator */ +.x { color: #f8f8f2 } /* Other */ +.p { color: #f8f8f2 } /* Punctuation */ +.ch { color: #75715e } /* Comment.Hashbang */ +.cm { color: #75715e } /* Comment.Multiline */ +.cp { color: #75715e } /* Comment.Preproc */ +.cpf { color: #75715e } /* Comment.PreprocFile */ +.c1 { color: #75715e } /* Comment.Single */ +.cs { color: #75715e } /* Comment.Special */ +.gd { color: #f92672 } /* Generic.Deleted */ +.ge { color: #f8f8f2; font-style: italic } /* Generic.Emph */ +.gr { color: #f8f8f2 } /* Generic.Error */ +.gh { color: #f8f8f2 } /* Generic.Heading */ +.gi { color: #a6e22e } /* Generic.Inserted */ +.go { color: #66d9ef } /* Generic.Output */ +.gp { color: #f92672; font-weight: bold } /* Generic.Prompt */ +.gs { color: #f8f8f2; font-weight: bold } /* Generic.Strong */ +.gu { color: #75715e } /* Generic.Subheading */ +.gt { color: #f8f8f2 } /* Generic.Traceback */ +.kc { color: #66d9ef } /* Keyword.Constant */ +.kd { color: #66d9ef } /* Keyword.Declaration */ +.kn { color: #f92672 } /* Keyword.Namespace */ +.kp { color: #66d9ef } /* Keyword.Pseudo */ +.kr { color: #66d9ef } /* Keyword.Reserved */ +.kt { color: #66d9ef } /* Keyword.Type */ +.ld { color: #e6db74 } /* Literal.Date */ +.m { color: #ae81ff } /* Literal.Number */ +.s { color: #e6db74 } /* Literal.String */ +.na { color: #a6e22e } /* Name.Attribute */ +.nb { color: #f8f8f2 } /* Name.Builtin */ +.nc { color: #a6e22e } /* Name.Class */ +.no { color: #66d9ef } /* Name.Constant */ +.nd { color: #a6e22e } /* Name.Decorator */ +.ni { color: #f8f8f2 } /* Name.Entity */ +.ne { color: #a6e22e } /* Name.Exception */ +.nf { color: #a6e22e } /* Name.Function */ +.nl { color: #f8f8f2 } /* Name.Label */ +.nn { color: #f8f8f2 } /* Name.Namespace */ +.nx { color: #a6e22e } /* Name.Other */ +.py { color: #f8f8f2 } /* Name.Property */ +.nt { color: #f92672 } /* Name.Tag */ +.nv { color: #f8f8f2 } /* Name.Variable */ +.ow { color: #f92672 } /* Operator.Word */ +.w { color: #f8f8f2 } /* Text.Whitespace */ +.mb { color: #ae81ff } /* Literal.Number.Bin */ +.mf { color: #ae81ff } /* Literal.Number.Float */ +.mh { color: #ae81ff } /* Literal.Number.Hex */ +.mi { color: #ae81ff } /* Literal.Number.Integer */ +.mo { color: #ae81ff } /* Literal.Number.Oct */ +.sa { color: #e6db74 } /* Literal.String.Affix */ +.sb { color: #e6db74 } /* Literal.String.Backtick */ +.sc { color: #e6db74 } /* Literal.String.Char */ +.dl { color: #e6db74 } /* Literal.String.Delimiter */ +.sd { color: #e6db74 } /* Literal.String.Doc */ +.s2 { color: #e6db74 } /* Literal.String.Double */ +.se { color: #ae81ff } /* Literal.String.Escape */ +.sh { color: #e6db74 } /* Literal.String.Heredoc */ +.si { color: #e6db74 } /* Literal.String.Interpol */ +.sx { color: #e6db74 } /* Literal.String.Other */ +.sr { color: #e6db74 } /* Literal.String.Regex */ +.s1 { color: #e6db74 } /* Literal.String.Single */ +.ss { color: #e6db74 } /* Literal.String.Symbol */ +.bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ +.fm { color: #a6e22e } /* Name.Function.Magic */ +.vc { color: #f8f8f2 } /* Name.Variable.Class */ +.vg { color: #f8f8f2 } /* Name.Variable.Global */ +.vi { color: #f8f8f2 } /* Name.Variable.Instance */ +.vm { color: #f8f8f2 } /* Name.Variable.Magic */ +.il { color: #ae81ff } /* Literal.Number.Integer.Long */ diff --git a/static/homepage.html b/static/homepage.html index aa566eb..a0ac06a 100644 --- a/static/homepage.html +++ b/static/homepage.html @@ -6,13 +6,11 @@