mygit

[UNMAINTAINED] A cgit/webgit alternative, written in Rust
Log | Files | Refs | README | LICENSE

commit 39d1609db0ec5cb8150ace1b94280f35aea4f1a2
parent 59544b7a83c93ce59831514802fd5e7bb8f9b9da
Author: Johann150 <johann@qwertqwefsday.eu>
Date:   Sun, 28 Mar 2021 23:45:27 +0200

use Solarized colour scheme, dark mode

To be able to use dark mode in the form of CSS's prefers-color-scheme,
syntect had to be switched to output classes instead of hard coded colours.

This is a bit problematic as seen in the changes on the stylesheet. Some of
the CSS classes could probably be merged, but this is a nontrivial problem.

Because of the increased size, we should enable Caching for the stylesheet,
which tide's serve_file does not automatically do.

Diffstat:
Msrc/main.rs | 31+++++++++++++++----------------
Mtemplates/static/style.css | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
2 files changed, 130 insertions(+), 44 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -6,7 +6,6 @@ use serde::Deserialize; use std::fs; use std::path::Path; use std::str; -use syntect::highlighting::ThemeSet; use syntect::parsing::SyntaxSet; use tide::Request; @@ -392,17 +391,16 @@ async fn repo_file(req: Request<()>) -> tide::Result { // TODO make sure I am escaping html properly here // TODO allow disabling of syntax highlighting // TODO -- dont pull in memory, use iterators if possible - let syntax_set = SyntaxSet::load_defaults_nonewlines(); + let syntax_set = SyntaxSet::load_defaults_newlines(); let extension = path .extension() .and_then(std::ffi::OsStr::to_str) .unwrap_or_default(); - let syntax_reference = syntax_set + let syntax = syntax_set .find_syntax_by_extension(extension) .unwrap_or_else(|| syntax_set.find_syntax_plain_text()); - let ts = ThemeSet::load_defaults(); - let theme = &ts.themes["InspiredGitHub"]; // TODO make customizable let tmpl = match tree_entry.to_object(&repo)?.into_tree() { + // this is a subtree Ok(tree) => RepoTreeTemplate { repo: &repo, tree, @@ -410,21 +408,22 @@ async fn repo_file(req: Request<()>) -> tide::Result { spec: &spec, } .into(), + // this is not a subtree, so it should be a blob i.e. file Err(tree_obj) => { + use syntect::{html::{ClassedHTMLGenerator, ClassStyle}, util::LinesWithEndings}; + + // get file contents from git object let file_string = str::from_utf8(tree_obj.as_blob().unwrap().content())?; - let mut highlighter = syntect::easy::HighlightLines::new(&syntax_reference, &theme); - let (mut output, bg) = syntect::html::start_highlighted_html_snippet(&theme); - for (n, line) in syntect::util::LinesWithEndings::from(file_string).enumerate() { - let regions = highlighter.highlight(line, &syntax_set); + // create a highlighter that uses CSS classes so we can use prefers-color-scheme + let mut highlighter = ClassedHTMLGenerator::new_with_class_style(&syntax, &syntax_set, ClassStyle::SpacedPrefixed{prefix:"code"}); + LinesWithEndings::from(file_string).for_each(|line| highlighter.parse_html_for_line_which_includes_newline(line)); + + let mut output = String::from("<pre>\n"); + for (n, line) in highlighter.finalize().lines().enumerate() { output.push_str(&format!( - "<a href='#L{0}' id='L{0}' class='line'>{0}</a>", - n + 1 + "<a href='#L{0}' id='L{0}' class='line'>{0}</a>{1}\n", + n + 1, line )); - syntect::html::append_highlighted_html_for_styled_line( - &regions[..], - syntect::html::IncludeBackground::IfDifferent(bg), - &mut output, - ); } output.push_str("</pre>\n"); diff --git a/templates/static/style.css b/templates/static/style.css @@ -5,7 +5,6 @@ body { margin: auto; font-family: "Archivo", Helvetica, Arial, Sans-serif; word-wrap: break-word; - background-color: white; line-height: 1.5; } @@ -13,10 +12,6 @@ body { max-width: 80ch; } -a:visited { - color: blue; -} - .repo-last-updated { font-style: italic; } @@ -53,10 +48,6 @@ a:visited { user-select: none; /* Non-prefixed version, currently */ } -:target { - background: #FFFACD; -} - .clone-url { font-family: "Roboto Mono", monospace; -webkit-user-select: all; /* Safari */ @@ -66,31 +57,24 @@ a:visited { hr.thin { border: 0; height: 0; - /* top border for light color scheme */ - border-top: 1px solid rgba(0, 0, 0, 0.1); - /* bottom border for dark color scheme */ - border-bottom: 1px solid rgba(255, 255, 255, 0.3); + border-top: 1px solid; } h1, h2, h3 { - margin: 0px; + margin: 0; } pre { line-height: 1.2; font-size: 1rem; overflow: auto; - margin: 0px; - padding: 0px; -} - -tr:hover { - background-color: #f0f0f0; + margin: 0; + padding: 0; } td { white-space: nowrap; - margin: 0px; + margin: 0; border-style:hidden; padding: 0; } @@ -114,17 +98,120 @@ table.core { } } +/* for code highlighting */ + +.markup.italic { + font-style: italic; +} + +.markup.bold { + font-weight: bold; +} + +/* +color scheme: Solarized +most of these classes are used by syntect + +Light is the default color scheme, not using a media query for browser support. +*/ +/* TODO simplify, e.g. merge CSS classes. */ + +.storage.modifier, .meta.scope.for-in-loop.shell, .variable.other.loop.shell, .meta.scope.case-block.shell, .meta.scope.case-body.shell { + color: #586e75; /* Solarized base01 */ +} + +body, .code, .keyword.operator.comparison, .keyword.operator.assignment, .keyword.operator.arithmetic, .meta.brace.round, .meta.brace.curly, .punctuation.section, .punctuation.section.block, .punctuation.definition.parameters, .punctuation.section.group, .meta.selector.css, .text.html.basic, .meta.tag.other.html, .text.html.basic, .meta.tag.any.html, .text.html.basic, .meta.tag.block.any, .text.html.basic, .meta.tag.inline.any, .text.html.basic, .meta.tag.structure.any.html, .text.html.basic, .source.js.embedded.html, .punctuation.separator.key-value.html, .variable.other.readwrite.js, .variable.other.object.js, .variable.other.constant.js { + color: #657b83; /* Solarized base00 */ +} + +hr.thin { + border-top-color: #657b83; /* Solarized base00 */ +} + +.punctuation.definition.string { + color: #839496; /* Solarized base0 */ +} + +.comment, .meta.documentation, .punctuation.definition.tag.html, .punctuation.definition.tag.begin, .punctuation.definition.tag.end, .meta.diff, .meta.diff.header, .constant.numeric.line-number.find-in-files { + color: #93a1a1; /* Solarized base1 */ +} + +:target, tr:hover, .links, .meta.paragraph.markdown, .meta.dummy.line-break { + background-color: #eee8d5; /* Solarized base2 */ +} + +body, .code { + background-color: #fdf6e3; /* Solarized base3 */ +} + +.variable.function, .keyword.control.class, .entity.name, .entity.name.class, .entity.name.type.class, .entity.other.attribute-name, .entity.name.function, .constant, .constant.language, .meta.preprocessor, .support.constant.color, .invalid.deprecated.color.w3c-non-standard-color-name.scss, .entity.name.tag.css, .entity.name.tag.scss, .source.less, .keyword.control.html.elements, .source.sass, .keyword.control.untitled, .entity.other.attribute-name.class, .entity.other.attribute-name.id, .text.html.basic, .entity.other.attribute-name.html, .meta.tag.xml, .entity.other.attribute-name, .variable.other.constant.ruby, .meta.array, .support.function.construct.php, .meta.group.braces.tex, .string.other.math.tex, .string.other.math.tex, .support.type.exception.python, .markup.heading, .punctuation.definition.heading.markdown, .markup.changed.git_gutter { + color: #b58900; /* Solarized yellow */ +} + +.meta.import, .keyword, .keyword.control.import, .keyword.control.import.from, .keyword.other.import, .keyword.control.at-rule.include, .keyword.control.at-rule.import, .entity.name.section, .constant.character, .constant.other, .support.type.exception, .keyword.other.special-method, .keyword.other.special-method.ruby, .entity.name.function.preprocessor.c, .meta.preprocessor.c.include, .meta.preprocessor.macro.c, .variable.parameter.function.latex, .support.function.section.latex { + color: #cb4b16; /* Solarized orange */ +} + +.constant.character.escape, .support.function.construct, .keyword.other.new, .punctuation.separator.continuation, .other.package.exclude, .other.remove, .punctuation.section.group.tex, .punctuation.definition.arguments.begin.latex, .punctuation.definition.arguments.end.latex, .punctuation.definition.arguments.latex, .punctuation.definition.constant.math.tex, .punctuation.definition.string.begin.tex, .punctuation.definition.string.end.tex, .variable.parameter.definition.label.latex, .punctuation.definition.logical-expression.shell, .markup.deleted, .markup.deleted.git_gutter { + color: #dc322f; /* Solarized red */ +} + +.variable.language { + color: #d33682; /* Solarized magenta */ +} + +.constant.numeric, .constant.other.reference.link.markdown { + color: #6c71c4; /* Solarized violet */ +} + +a, .variable, .entity.other.inherited-class, .entity.name.tag, .storage.type, .meta.brace.square, .punctuation.section.brackets, .entity.other.attribute-name.pseudo-element, .entity.other.attribute-name.tag.pseudo-element, .entity.other.attribute-name.pseudo-class, .entity.other.attribute-name.tag.pseudo-class, .support.function.perl, .meta.diff.range { + color: #268bd2; /* Solarized blue */ +} + +.string, .string.regexp, .string.quoted.double, .string.quoted.single, .constant.other.symbol.ruby, .meta.preprocessor.c.include, .string.quoted.other.lt-gt.include.c, .meta.preprocessor.c.include, .punctuation.definition.string.begin.c, .meta.preprocessor.c.include, .punctuation.definition.string.end.c, .other.add, .text.tex.latex, .constant.other.math.tex, .constant.other.general.math.tex, .constant.other.general.math.tex, .constant.character.math.tex, .keyword.control.label.latex, .text.tex.latex, .constant.other.general.math.tex, .support.function.general.tex, .keyword.control.ref.latex, .markup.changed, .markup.underline.link.markdown, .meta.link.reference, .constant.other.reference.link.markdown, .entity.name.filename.find-in-files { + color: #2aa198; /* Solarized cyan */ +} + +.keyword, .storage, .support, .support.type, .support.class, .punctuation.definition.variable, .support.function, .keyword.other.special-method.ruby, .support.function.be.latex, .storage.type.class.python, .storage.type.function.python, .storage.modifier.global.python, .storage.modifier.c++, .markup.inserted, .markup.quote, .markup.inserted.git_gutter { + color: #859900; /* Solarized green */ +} + +.invalid { + background-color: #ec9489; +} + +/* Dark colour scheme for browsers that support it. */ + @media (prefers-color-scheme: dark) { - body { - background: #212529; - color: #f8f9fa; + .storage.modifier, .meta.scope.for-in-loop.shell, .variable.other.loop.shell, .meta.scope.case-block.shell, .meta.scope.case-body.shell { + color: #93a1a1; /* Solarized base1 */ + } + + body, .code, .keyword.operator.comparison, .keyword.operator.assignment, .keyword.operator.arithmetic, .meta.brace.round, .meta.brace.curly, .punctuation.section, .punctuation.section.block, .punctuation.definition.parameters, .punctuation.section.group, .meta.selector.css, .text.html.basic, .meta.tag.other.html, .text.html.basic, .meta.tag.any.html, .text.html.basic, .meta.tag.block.any, .text.html.basic, .meta.tag.inline.any, .text.html.basic, .meta.tag.structure.any.html, .text.html.basic, .source.js.embedded.html, .punctuation.separator.key-value.html, .variable.other.readwrite.js, .variable.other.object.js, .variable.other.constant.js { + color: #839496; /* Solarized base0 */ + } + + hr.thin { + border-top-color: #839496; /* Solarized base0 */ + } + + .punctuation.definition.string { + color: #657b83; /* Solarized base00 */ + } + + .comment, .meta.documentation, .punctuation.definition.tag.html, .punctuation.definition.tag.begin, .punctuation.definition.tag.end, .meta.diff, .meta.diff.header, .constant.numeric.line-number.find-in-files { + color: #586e75; /* Solarized base01 */ + } + + :target, tr:hover, .links, .meta.paragraph.markdown, .meta.dummy.line-break { + background-color: #073642; /* Solarized base02 */ } - :target { - background: #ffffff; + body, .code { + background-color: #002b36; /* Solarized base03 */ } - tr:hover { - background-color: #0f0f0f; + .invalid { + background-color: #6e2e32; } }