aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTolmachev Igor <me@igorek.dev>2026-01-06 06:50:50 +0900
committerTolmachev Igor <me@igorek.dev>2026-01-06 06:50:50 +0900
commit4f14cdffbf165cb3a5b48f5bf5a1b58e515e2ec4 (patch)
tree499b428e207206d92396d66c23a8567fc4967be4
parent86ffad6fa449cdd56f895eb8faff3ee72456f4ef (diff)
downloadcgit_material_docker-4f14cdffbf165cb3a5b48f5bf5a1b58e515e2ec4.tar.gz
cgit_material_docker-4f14cdffbf165cb3a5b48f5bf5a1b58e515e2ec4.zip
Add material highlight
-rw-r--r--Dockerfile5
-rw-r--r--cgitrc2
-rw-r--r--responsive/cgit.css359
-rwxr-xr-xresponsive/md2html37
-rwxr-xr-xresponsive/syntax-material.py37
5 files changed, 423 insertions, 17 deletions
diff --git a/Dockerfile b/Dockerfile
index 516f38a..df191eb 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -15,11 +15,14 @@ RUN make install
15COPY cgitrc /app 15COPY cgitrc /app
16COPY responsive/head.html /app/www/static 16COPY responsive/head.html /app/www/static
17COPY responsive/cgit.css /app/www/static 17COPY responsive/cgit.css /app/www/static
18COPY responsive/syntax-material.py /app/lib/filters
19COPY responsive/md2html /app/lib/filters/html-converters/md2html
18 20
19FROM debian:latest AS cgit-run 21FROM debian:latest AS cgit-run
20 22
21RUN apt-get update 23RUN apt-get update
22RUN apt-get install -y python3 python3-pygments lighttpd 24RUN apt-get install -y python3 python3-pygments python3-markdown python3-docutils
25RUN apt-get install -y lighttpd
23 26
24WORKDIR /app 27WORKDIR /app
25COPY --from=cgit-build /app /app 28COPY --from=cgit-build /app /app
diff --git a/cgitrc b/cgitrc
index 99ecefa..981ab64 100644
--- a/cgitrc
+++ b/cgitrc
@@ -5,6 +5,6 @@ favicon=/static/favicon.ico
5head-include=/app/www/static/head.html 5head-include=/app/www/static/head.html
6 6
7about-filter=/app/lib/filters/about-formatting.sh 7about-filter=/app/lib/filters/about-formatting.sh
8source-filter=/app/lib/filters/syntax-highlighting.py 8source-filter=/app/lib/filters/syntax-material.py
9 9
10include=/app/etc/cgitrc 10include=/app/etc/cgitrc
diff --git a/responsive/cgit.css b/responsive/cgit.css
index f9e1b76..c69b01c 100644
--- a/responsive/cgit.css
+++ b/responsive/cgit.css
@@ -556,27 +556,356 @@ div#cgit div.error {
556 } 556 }
557} 557}
558 558
559/* --- Fix Syntax Highlighting Alignment --- */ 559/* Container override for highlighted code to handle font sizing */
560div#cgit table.blob pre {
561 font-family: "JetBrains Mono", "Fira Code", monospace;
562 font-size: 0.95em;
563 line-height: 1.4;
564}
560 565
561/* 1. Reset margins and padding added by syntax highlighting */ 566/* --- Syntax Highlighting Mapping to Material Variables --- */
562div#cgit table.blob td.lines div.highlight { 567
563 margin: 0; 568/* Comments - Outline/Grey */
564 padding: 0; 569.hl-c,
565 border: none; 570.hl-cm,
571.hl-cp,
572.hl-c1,
573.hl-cs {
574 color: var(--color-outline);
575 font-style: italic;
566} 576}
567 577
568/* 2. Force alignment of line height and fonts */ 578/* Keywords - Primary (Pinkish/Orange) */
569div#cgit table.blob td.linenumbers pre, 579.hl-k,
570div#cgit table.blob td.lines pre { 580.hl-kc,
571 font-family: monospace; 581.hl-kd,
572 font-size: 14px; 582.hl-kn,
573 line-height: 1.5 !important; 583.hl-kp,
584.hl-kr,
585.hl-kt {
586 color: var(--color-primary);
587 font-weight: bold;
588}
589
590/* Names/Functions - Tertiary (Yellowish) */
591.hl-n,
592.hl-na,
593.hl-nb,
594.hl-nc,
595.hl-no,
596.hl-nd,
597.hl-ni,
598.hl-ne,
599.hl-nf,
600.hl-nl,
601.hl-nn,
602.hl-nt,
603.hl-nv,
604.hl-nx {
605 color: var(--color-tertiary);
606}
607
608/* Strings - Secondary (Reddish/Brownish) */
609.hl-s,
610.hl-sa,
611.hl-sb,
612.hl-sc,
613.hl-dl,
614.hl-sd,
615.hl-s2,
616.hl-se,
617.hl-sh,
618.hl-si,
619.hl-sx,
620.hl-sr,
621.hl-s1,
622.hl-ss {
623 color: var(--color-secondary);
624}
625
626/* Operators - On Surface (Main text color) */
627.hl-o,
628.hl-ow {
629 color: var(--color-on-surface-variant);
630}
631
632/* Numbers - Primary Container (Brighter accent) */
633.hl-m,
634.hl-mb,
635.hl-mf,
636.hl-mh,
637.hl-mi,
638.hl-mo,
639.hl-il {
640 color: var(--color-primary-fixed);
641}
642
643/* Errors */
644.hl-err,
645.hl-gr {
646 color: var(--color-error);
647 background-color: var(--color-error-container);
648}
649
650/* Generic Deleted */
651.hl-gd {
652 color: var(--color-error);
653 background-color: var(--color-error-container);
654}
655
656/* Generic Inserted */
657.hl-gi {
658 color: var(--color-tertiary);
659 background-color: var(--color-tertiary-container);
660}
661
662/* --- Markdown Body Styles (Material Design) --- */
663
664.markdown-body {
665 font-family: inherit;
666 font-size: 1rem;
667 line-height: 1.6;
668 color: var(--color-on-background);
669 word-wrap: break-word;
670}
671
672/* Headers */
673.markdown-body h1,
674.markdown-body h2,
675.markdown-body h3,
676.markdown-body h4,
677.markdown-body h5,
678.markdown-body h6 {
679 margin-top: 24px;
680 margin-bottom: 16px;
681 font-weight: 600;
682 line-height: 1.25;
683 color: var(--color-on-surface);
684}
685
686.markdown-body h1 {
687 font-size: 2em;
688 border-bottom: 1px solid var(--color-outline-variant);
689 padding-bottom: 0.3em;
690}
691.markdown-body h2 {
692 font-size: 1.5em;
693 border-bottom: 1px solid var(--color-outline-variant);
694 padding-bottom: 0.3em;
695}
696.markdown-body h3 {
697 font-size: 1.25em;
698}
699.markdown-body h4 {
700 font-size: 1em;
701}
702.markdown-body h5 {
703 font-size: 0.875em;
704}
705.markdown-body h6 {
706 font-size: 0.85em;
707 color: var(--color-on-surface-variant);
708}
709
710/* Links */
711.markdown-body a {
712 color: var(--color-primary);
713 text-decoration: none;
714}
715.markdown-body a:hover {
716 text-decoration: underline;
717}
718
719/* Paragraphs & Lists */
720.markdown-body p,
721.markdown-body blockquote,
722.markdown-body ul,
723.markdown-body ol,
724.markdown-body dl,
725.markdown-body table,
726.markdown-body pre {
574 margin-top: 0; 727 margin-top: 0;
728 margin-bottom: 16px;
575} 729}
576 730
577/* 3. Remove impact of first <pre> */ 731.markdown-body hr {
578div#cgit table.blob td.lines > pre { 732 height: 0.25em;
579 white-space: normal; 733 padding: 0;
734 margin: 24px 0;
735 background-color: var(--color-outline-variant);
736 border: 0;
737}
738
739/* Blockquotes */
740.markdown-body blockquote {
741 padding: 0 1em;
742 color: var(--color-on-surface-variant);
743 border-left: 0.25em solid var(--color-outline);
744 background-color: var(--color-surface-container-low);
745}
746
747/* Tables */
748.markdown-body table {
749 display: block;
750 width: 100%;
751 overflow: auto;
752 border-spacing: 0;
753 border-collapse: collapse;
754}
755
756.markdown-body table th {
757 font-weight: 600;
758 background-color: var(--color-surface-container);
759}
760
761.markdown-body table th,
762.markdown-body table td {
763 padding: 6px 13px;
764 border: 1px solid var(--color-outline-variant);
765}
766
767.markdown-body table tr {
768 background-color: var(--color-surface);
769 border-top: 1px solid var(--color-outline-variant);
770}
771
772.markdown-body table tr:nth-child(2n) {
773 background-color: var(--color-surface-container-lowest);
774}
775
776/* Images */
777.markdown-body img {
778 max-width: 100%;
779 box-sizing: border-box;
780 background-color: var(--color-surface);
781 border-radius: 4px;
782}
783
784/* Code Blocks & Inline Code */
785.markdown-body code,
786.markdown-body tt {
787 padding: 0.2em 0.4em;
580 margin: 0; 788 margin: 0;
789 font-size: 85%;
790 font-family: "JetBrains Mono", "Fira Code", monospace;
791 background-color: var(--color-surface-container-high);
792 border-radius: 6px;
793 color: var(--color-on-surface);
794}
795
796.markdown-body pre {
797 padding: 16px;
798 overflow: auto;
799 font-size: 85%;
800 line-height: 1.45;
801 background-color: var(--color-surface-container-lowest);
802 border-radius: 6px;
803 border: 1px solid var(--color-outline-variant);
804}
805
806.markdown-body pre code,
807.markdown-body pre tt {
808 display: inline;
809 max-width: auto;
581 padding: 0; 810 padding: 0;
811 margin: 0;
812 overflow: visible;
813 line-height: inherit;
814 word-wrap: normal;
815 background-color: transparent;
816 border: 0;
817}
818
819/* Anchors (Permalinks) */
820.markdown-body .headerlink {
821 float: left;
822 padding-right: 4px;
823 margin-left: -20px;
824 line-height: 1;
825 color: var(--color-primary);
826 text-decoration: none;
827 opacity: 0;
828 transition: opacity 0.2s;
829}
830
831.markdown-body h1:hover .headerlink,
832.markdown-body h2:hover .headerlink,
833.markdown-body h3:hover .headerlink,
834.markdown-body h4:hover .headerlink,
835.markdown-body h5:hover .headerlink,
836.markdown-body h6:hover .headerlink {
837 opacity: 1;
838}
839
840/* Pygments Syntax Highlighting within Markdown
841 (Mapping standard Pygments classes to Material Variables) */
842.markdown-body .highlight .c,
843.markdown-body .highlight .cm,
844.markdown-body .highlight .cp,
845.markdown-body .highlight .c1,
846.markdown-body .highlight .cs {
847 color: var(--color-outline);
848 font-style: italic;
849}
850.markdown-body .highlight .k,
851.markdown-body .highlight .kc,
852.markdown-body .highlight .kd,
853.markdown-body .highlight .kn,
854.markdown-body .highlight .kp,
855.markdown-body .highlight .kr,
856.markdown-body .highlight .kt {
857 color: var(--color-primary);
858 font-weight: bold;
859}
860.markdown-body .highlight .n,
861.markdown-body .highlight .na,
862.markdown-body .highlight .nb,
863.markdown-body .highlight .nc,
864.markdown-body .highlight .no,
865.markdown-body .highlight .nd,
866.markdown-body .highlight .ni,
867.markdown-body .highlight .ne,
868.markdown-body .highlight .nf,
869.markdown-body .highlight .nl,
870.markdown-body .highlight .nn,
871.markdown-body .highlight .nt,
872.markdown-body .highlight .nv,
873.markdown-body .highlight .nx {
874 color: var(--color-tertiary);
875}
876.markdown-body .highlight .s,
877.markdown-body .highlight .sa,
878.markdown-body .highlight .sb,
879.markdown-body .highlight .sc,
880.markdown-body .highlight .dl,
881.markdown-body .highlight .sd,
882.markdown-body .highlight .s2,
883.markdown-body .highlight .se,
884.markdown-body .highlight .sh,
885.markdown-body .highlight .si,
886.markdown-body .highlight .sx,
887.markdown-body .highlight .sr,
888.markdown-body .highlight .s1,
889.markdown-body .highlight .ss {
890 color: var(--color-secondary);
891}
892.markdown-body .highlight .m,
893.markdown-body .highlight .mb,
894.markdown-body .highlight .mf,
895.markdown-body .highlight .mh,
896.markdown-body .highlight .mi,
897.markdown-body .highlight .mo,
898.markdown-body .highlight .il {
899 color: var(--color-primary-fixed);
900}
901.markdown-body .highlight .o,
902.markdown-body .highlight .ow {
903 color: var(--color-on-surface-variant);
904}
905.markdown-body .highlight .g,
906.markdown-body .highlight .gh,
907.markdown-body .highlight .gu,
908.markdown-body .highlight .gd,
909.markdown-body .highlight .gi {
910 color: var(--color-on-surface);
582} 911}
diff --git a/responsive/md2html b/responsive/md2html
new file mode 100755
index 0000000..571c8d7
--- /dev/null
+++ b/responsive/md2html
@@ -0,0 +1,37 @@
1#!/usr/bin/env python3
2import io
3import sys
4
5import markdown
6from markdown.extensions.toc import TocExtension
7
8sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding="utf-8")
9sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
10
11sys.stdout.write("<div class='markdown-body'>")
12sys.stdout.flush()
13
14try:
15 markdown.markdownFromFile(
16 output_format="html5",
17 extensions=[
18 "markdown.extensions.fenced_code",
19 "markdown.extensions.codehilite",
20 "markdown.extensions.tables",
21 "markdown.extensions.sane_lists",
22 "markdown.extensions.admonition",
23 TocExtension(anchorlink=True, permalink=True),
24 ],
25 extension_configs={
26 "markdown.extensions.codehilite": {
27 "css_class": "highlight",
28 "guess_lang": False,
29 }
30 },
31 )
32except Exception as e:
33 sys.stdout.write(f"<p>Error rendering markdown: {e}</p>")
34 sys.stdin.seek(0)
35 sys.stdout.write(f"<pre>{sys.stdin.read()}</pre>")
36
37sys.stdout.write("</div>")
diff --git a/responsive/syntax-material.py b/responsive/syntax-material.py
new file mode 100755
index 0000000..3176691
--- /dev/null
+++ b/responsive/syntax-material.py
@@ -0,0 +1,37 @@
1#!/usr/bin/env python3
2import sys
3
4from pygments import highlight
5from pygments.formatters import HtmlFormatter
6from pygments.lexers import get_lexer_for_filename, guess_lexer
7from pygments.util import ClassNotFound
8
9
10def main():
11 filename = sys.argv[-1] if len(sys.argv) > 1 else "stdin"
12
13 try:
14 data = sys.stdin.read()
15 except Exception:
16 return
17
18 try:
19 lexer = get_lexer_for_filename(filename)
20 except ClassNotFound:
21 try:
22 lexer = guess_lexer(data)
23 except ClassNotFound:
24 sys.stdout.write(f"<pre>{data}</pre>")
25 return
26
27 formatter = HtmlFormatter(style="default", nowrap=True, classprefix="hl-")
28
29 try:
30 sys.stdout.write("<style>.hl- { display: inline; }</style>")
31 highlight(data, lexer, formatter, sys.stdout)
32 except BrokenPipeError:
33 pass
34
35
36if __name__ == "__main__":
37 main()