From 3eac461f7a6ad8740c39df3245c81edae7797b24 Mon Sep 17 00:00:00 2001 From: alexander Date: Sun, 18 Jan 2026 23:36:55 +0100 Subject: [PATCH] Finsihed --- .gitignore | 8 +- .vscode/settings.json | 3 + .vscode/tasks.json | 40 +++++++-- Caddyfile | 6 ++ Dockerfile | 13 +++ cheatsheet_inventory.json | 59 +++++++++++++ docker-compose.yml | 6 ++ requirements.txt | 20 +++++ src/__pycache__/inventory.cpython-312.pyc | Bin 0 -> 3584 bytes src/build.py | 54 ++++++++++++ src/inventory.py | 58 +++++++++++++ styles/main.scss | 100 ++++++++++++++++++++++ templates/impressum.html.j2 | 58 +++++++++++++ templates/index.html.j2 | 53 ++++++++++++ templates/license.html.j2 | 27 ++++++ templates/navbar.j2 | 8 ++ 16 files changed, 506 insertions(+), 7 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 Caddyfile create mode 100644 Dockerfile create mode 100644 cheatsheet_inventory.json create mode 100644 docker-compose.yml create mode 100644 requirements.txt create mode 100644 src/__pycache__/inventory.cpython-312.pyc create mode 100644 src/build.py create mode 100644 src/inventory.py create mode 100644 styles/main.scss create mode 100644 templates/impressum.html.j2 create mode 100644 templates/index.html.j2 create mode 100644 templates/license.html.j2 create mode 100644 templates/navbar.j2 diff --git a/.gitignore b/.gitignore index 5ceb386..e22a42c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ -venv +.venv +out +node_modules +__pycache__/ + +package-lock.json +package.json \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0e0dcd2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 753f867..ca8a0f3 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,17 +1,45 @@ { "tasks": [ { - "label": "Compile All", + "label": "Run build Script", "type": "shell", - "command": "TYPST_SOURCE_DIR=src BUILD_DIR=output ./compile-all.bash", + "command": "${workspaceFolder}/.venv/bin/python", + "args": ["src/build.py"], + "group": { + "kind": "build", + "isDefault": true + } + }, + { + "label": "Watch Styles", + "type": "shell", + "command": "sass", + "args": ["--watch", "styles:static/css"], + "isBackground": true, + "problemMatcher": { + "pattern": { + "regexp": "^.*$", + "file": 1, + "location": 2, + "message": 3 + }, + "background": { + "activeOnStart": true, + "beginsPattern": "^.*Watching.*$", + "endsPattern": "^.*Watching.*$" + } + } + }, + { + "label": "Run debug server", + "type": "shell", + "command": "${workspaceFolder}/.venv/bin/python", + "args": ["src/debug_server.py"], "group": { "kind": "build", "isDefault": true - }, - "problemMatcher": [], - "options": { - "cwd": "${workspaceFolder}" } } + ] } diff --git a/Caddyfile b/Caddyfile new file mode 100644 index 0000000..d0cef44 --- /dev/null +++ b/Caddyfile @@ -0,0 +1,6 @@ +:8000 { + root * /www + file_server + + encode gzip +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..faf1d83 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM python:3.11 AS build + +WORKDIR /workdir +COPY . . + +RUN pip install --no-cache-dir -r ./requirements.txt +RUN python3 src/build.py + +FROM caddy:latest AS serve + +COPY --from=build /workdir/out/ /www/ +COPY --from=build /workdir/Caddyfile /etc/caddy/Caddyfile + diff --git a/cheatsheet_inventory.json b/cheatsheet_inventory.json new file mode 100644 index 0000000..18c7652 --- /dev/null +++ b/cheatsheet_inventory.json @@ -0,0 +1,59 @@ +{ + "items": [ + { + "url": "https://github.com/user/python-cheatsheet", + "cache": true, + "id": "550e8400-e29b-41d4-a716-446655440000", + "title": "Python Basics Cheatsheet", + "author": "John Doe", + "git_commit": "abc123def456", + "git_repo": "https://github.com/user/python-cheatsheet", + "git_repo_type": "github", + "date": "2025-01-15" + }, + { + "url": "https://example.com/js-guide.pdf", + "cache": false, + "id": "550e8400-e29b-41d4-a716-446655440001", + "title": "JavaScript Quick Reference", + "author": null, + "git_commit": null, + "git_repo": null, + "git_repo_type": "external", + "date": "2025-01-10" + }, + { + "url": "https://gitlab.com/team/react-patterns", + "cache": true, + "id": "550e8400-e29b-41d4-a716-446655440002", + "title": "React Design Patterns", + "author": "Jane Smith", + "git_commit": "xyz789abc", + "git_repo": "https://gitlab.com/team/react-patterns", + "git_repo_type": "gitlab", + "date": "2025-01-08" + }, + { + "url": "https://raw.githubusercontent.com/latex4ei/Computertechnik/gh-pages/Computertechnik.pdf", + "cache": false, + "id": "550e8400-e29b-41d4-a716-446655440003", + "title": "CSS Tips & Tricks", + "author": "Alex Johnson", + "git_commit": null, + "git_repo": "https://github.com/awesome/css-tips", + "git_repo_type": "github", + "date": "2024-12-20" + }, + { + "url": "https://raw.githubusercontent.com/latex4ei/Computertechnik/gh-pages/Computertechnik.pdf", + "cache": true, + "id": "550e8400-e29b-41d4-a716-446655440004", + "title": "Docker & Kubernetes Guide", + "author": null, + "git_commit": "dev-2025-01-18", + "git_repo": "https://gitea.company.com/internal/devops", + "git_repo_type": "gitea", + "date": "2025-01-18" + } + ] +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..172cd75 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,6 @@ + +services: + server_html: + build: . + ports: + - "8000:8000" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..0b56b46 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,20 @@ +annotated-types==0.7.0 +blinker==1.9.0 +certifi==2026.1.4 +charset-normalizer==3.4.4 +click==8.3.1 +Flask==3.1.2 +idna==3.11 +itsdangerous==2.2.0 +Jinja2==3.1.6 +libsass==0.23.0 +livereload==2.7.1 +MarkupSafe==3.0.3 +pydantic==2.12.5 +pydantic_core==2.41.5 +requests==2.32.5 +tornado==6.5.4 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +urllib3==2.6.3 +Werkzeug==3.1.5 diff --git a/src/__pycache__/inventory.cpython-312.pyc b/src/__pycache__/inventory.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d840737c9efde01d2c5b20f5502b16d673feb719 GIT binary patch literal 3584 zcmb_fU2Idy6`uQNU;i7zIzZVbCD7m%i3J<}#1fU?-B6LOl&%ndsCDBRC)Zs2dgopf z5`|SHsDvxjI8vo#)mEE_K4b+__mO>TtM;icNo_6ZKvksjvTuOW>Yg?L+Tadt$kXbe4eii|X_!T5 zgoO(#jowqUQ5s`9jeEKXRi?nkLVzYD7BVngWf#N zn};g`Er|xvFzD-T{ZLy!ytOj2B}Gx145niuesP=`t~1VD7-i<93N< z42#`1%9QcUPq67PGPIM&kzvMo3fY6k6pn;r_l8=Z!Hr+@z37c_%LHe7zImJJ2jLqW zSqgp*IulJ#)Z;6WuBO`6G8@N*S}-jp0-U*3Ue0f284Tg(=!x|!poI(su|-A9%{D4x zs+eYAj2rMriXmUxZrzA4PXjbl1#oIJI*NFzHuCd-d;izg zYdhDUAa~?xxrj;HM$=Leo!v$>@F?i->$lz`0guMR%^Q)(v@}9`$T8wb6Y!keAQJqc z?zVD+Oh{>cI4$uW*jY$?N~^kszSDpPIxFXGYL>@@H1RDaBIp7pU{l#mhlFf9Lai9? zxCpS@;C07ytmuFwXIAc(VVMX4xuRp2g=$wAaLx>XlL-#dBNDB7v|6fobJ7Ywj0Py2 zIYKHpc%9wd-CnYbeU@#|9ANP#MCZ0}kDr2hm@iHZ*bI3ViOrs>otho24K5sNM!KHG zdzVI=@nbdRMZEV({On5n?6YXHzNhXiUT;SGo&I2XC>LQbZj}<(@6F;_5PO%Ojrw$XkzB-%iy;B%E6rd z<9i1$q?A9UvzPpu`MGV9? z`u}`IBJR8X#{bKX)0%HL-I4%l0@Hyaz7lP;?YTFR#QlLknFh9Z1vJs#M3@JioA?qO zo{GZL;R15>{S?ZBsf1CfSZ3aP>@yWw;E1tPYCniVo*12qjTpBW?Z!u-+qKiXgwENg zRR$;{lriRV3}!%}n<5C90L79cg8A0|pfQ|r%N!K}XWTe`;w0~bxx612s72c>i_kc` zP0cabjAu}*m2N^#@?$vdeNR#0CO}+}pGMUgWccEHHH{&3+#jIL5Fs?r!6JsAgmDMo z5`ZkE7HoA;d!pP1T^vi5UY!1KU;tQpayD9v)<@>A&s}fm@6McGjYMY$elbu#KR+}# zG=FXG+G2lW&#~nbSN^u=%4(wHISikvote4xB9WT?toGRgZ6tbTK6;VdJs+G4&PV5> z3)h$SK1rWlNuO<`&n+Jrd`y>rc(IYZG&A&K8y$ah@QdEhd%rmP`O(E&OB0R#r<#$| z&-C!DUekZId%kn7bN;~GfrY~2SYuazQ_s8z#U6~#j@8Cyt(vuPa`8+f-nZm7LIa4A zsmGF!k?MmOf?{eTK(z4v%)*(bdiZ%{&$7DbWdzjT>=ruy`PA;qUCLj&w97|=>A27< zlhi1?W}YJ$dUc;r@!trqT5dV CheatsheetInvertoryConfig: + if not os.path.exists(file): + res = CheatsheetInvertoryConfig(items=[]) + else: + res = CheatsheetInvertoryConfig.model_validate_json( + open(file, "r", encoding="utf-8").read() + ) + + with open(file, "w", encoding="utf-8") as f: + f.write(res.model_dump_json(indent=4)) + + return res + +def download_cheatsheet(inv: CheatsheetItem, outdir: str) -> str | None: + r = requests.get(inv.url) + if not r.ok and r.headers.get("Content-Type") != "application/pdf": + return None + + data = r.content + + hashdata = hashlib.sha256(data) + + filesname = os.path.join("cache", f"{hashdata.hexdigest()}.pdf") + + if not os.path.exists(os.path.join(outdir, "cache")): + os.mkdir(os.path.join(outdir, "cache")) + + with open(os.path.join(outdir, filesname), "wb") as f: + f.write(data) + + print("Saved file to", filesname) + + return filesname diff --git a/styles/main.scss b/styles/main.scss new file mode 100644 index 0000000..e222248 --- /dev/null +++ b/styles/main.scss @@ -0,0 +1,100 @@ +/* + * Styles for the Formelsammlung project + * 90's inspired aesthetic + */ + +body { + background-color: #e8e8e8; + font-family: 'Trebuchet MS', Arial, sans-serif; + color: #333; + margin: 0; + padding: 0; + font-size: 14px; + + padding-left: 20px; + padding-right: 20px; + + width: calc(100vw - 40px); +} + +/* Navbar styles */ +nav.navbar { + background-color: #c0c0c0; + border-bottom: 2px solid #999; + padding: 15px 20px; + display: flex; + justify-content: space-between; + align-items: center; + box-shadow: inset 1px 1px 0 #ffffff, inset -1px -1px 0 #808080; +} + +nav.navbar h3 { + margin: 0; + font-size: 18px; + color: #0051ba; + font-weight: bold; +} + +nav.navbar a { + color: #0051ba; + text-decoration: none; + margin-left: 20px; + padding: 5px 10px; + border: 1px solid transparent; + transition: all 0.2s ease; +} + +nav.navbar a:hover { + border: 1px solid #0051ba; + background-color: #dfdfdf; +} + +/* Main content area padding */ +body > h1, +body > table { + margin-left: 20px; + margin-right: 20px; +} + +h1 { + color: #0051ba; + text-align: center; + font-weight: bold; + border-bottom: 2px solid #0051ba; + padding-bottom: 10px; +} + +table { + width: calc(100% - 40px); + border-collapse: collapse; + margin-top: 20px; + background-color: #ffffff; +} + +table, th, td { + border: 1px solid #999; +} + +th, td { + padding: 8px; + text-align: left; +} + +th { + background-color: #c0c0c0; + font-weight: bold; +} + +tbody tr:hover { + background-color: #e8e8ff; +} + +/* Preserve whitespace and line breaks */ +.license-text { + white-space: pre-wrap; + word-wrap: break-word; + font-family: 'Courier New', monospace; + background-color: #f5f5f5; + padding: 10px; + border: 1px solid #999; +} diff --git a/templates/impressum.html.j2 b/templates/impressum.html.j2 new file mode 100644 index 0000000..277a1ab --- /dev/null +++ b/templates/impressum.html.j2 @@ -0,0 +1,58 @@ + + + + + + + FS² + + + {% include "navbar.j2" %} + +

Impressum

+

Angaben gemäß § 5 DDG

+

+ Max Muster - Musterberuf
+ c/o Beispielbüro
+ Musterweg
+ 12345 Musterstadt
+

+

+ Vertreten durch:
+ Max Muster
+

+ +

+ Kontakt:
+ Telefon: 01234-789456
+ Fax: 1234-56789
+ E-Mail: max@muster.de +

+ +

+ Aufsichtsbehörde:
+ Musteraufsicht Musterstadt
+

+ +

+ Verantwortlich für den Inhalt nach § 18 Abs. 2 MStV:
+ Max Muster
+ Musterweg
+ 12345 Musterstadt
+ +

+

+ Verbraucherstreitbeilegung / Universalschlichtungsstelle +
Wir nehmen nicht an Streitbeilegungsverfahren vor einer Verbraucherschlichtungsstelle teil und sind dazu auch nicht verpflichtet. +

+ +

+ Haftungsausschluss:

+ Haftung für Inhalte
+ Die Inhalte unserer Seiten wurden mit größter Sorgfalt erstellt. Für die Richtigkeit, Vollständigkeit und Aktualität der Inhalte können wir jedoch keine Gewähr übernehmen. Als Diensteanbieter sind wir gemäß § 7 Abs.1 DDG für eigene Inhalte auf diesen Seiten nach den allgemeinen Gesetzen verantwortlich. Nach §§ 8 bis 10 DDG sind wir als Diensteanbieter jedoch nicht verpflichtet, übermittelte oder gespeicherte fremde Informationen zu überwachen oder nach Umständen zu forschen, die auf eine rechtswidrige Tätigkeit hinweisen. Verpflichtungen zur Entfernung oder Sperrung der Nutzung von Informationen nach den allgemeinen Gesetzen bleiben hiervon unberührt. Eine diesbezügliche Haftung ist jedoch erst ab dem Zeitpunkt der Kenntnis einer konkreten Rechtsverletzung möglich. Bei Bekanntwerden von entsprechenden Rechtsverletzungen werden wir diese Inhalte umgehend entfernen.

+ + Haftung für Links
+ Unser Angebot enthält Links zu externen Webseiten Dritter, auf deren Inhalte wir keinen Einfluss haben. Deshalb können wir für diese fremden Inhalte auch keine Gewähr übernehmen. Für die Inhalte der verlinkten Seiten ist stets der jeweilige Anbieter oder Betreiber der Seiten verantwortlich. Die verlinkten Seiten wurden zum Zeitpunkt der Verlinkung auf mögliche Rechtsverstöße überprüft. Rechtswidrige Inhalte waren zum Zeitpunkt der Verlinkung nicht erkennbar. Eine permanente inhaltliche Kontrolle der verlinkten Seiten ist jedoch ohne konkrete Anhaltspunkte einer Rechtsverletzung nicht zumutbar. Bei Bekanntwerden von Rechtsverletzungen werden wir derartige Links umgehend entfernen. +

+ + \ No newline at end of file diff --git a/templates/index.html.j2 b/templates/index.html.j2 new file mode 100644 index 0000000..f2fd315 --- /dev/null +++ b/templates/index.html.j2 @@ -0,0 +1,53 @@ + + + + + + + FS² + + + {% include "navbar.j2" %} + +

Formel(sammlung)²

+ + + + + + + + + + + {% for item in items %} + + + + + + + {% endfor %} + +
TitleRepoUpload DateGit commit
+ {{ item.title }} + + {% if item.author %} +
by {{ item.author }} + {% endif %} +
+ {% if item.git_repo %} + {{ item.git_repo_type }} + {% else %} + N/A + {% endif %} + + {{ item.date }} + + {% if item.git_repo %} + {{ item.git_commit }} + {% endif %} +
+ + + \ No newline at end of file diff --git a/templates/license.html.j2 b/templates/license.html.j2 new file mode 100644 index 0000000..f752cf3 --- /dev/null +++ b/templates/license.html.j2 @@ -0,0 +1,27 @@ + + + + + + + FS² + + + {% include "navbar.j2" %} + +

License

+ +

+Copyright {{thisYear}} Alexander +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +

+ +

+ Cheatsheets are licensed under their respective licenses as indicated in their Git repositories. +

+ + \ No newline at end of file diff --git a/templates/navbar.j2 b/templates/navbar.j2 new file mode 100644 index 0000000..a22591e --- /dev/null +++ b/templates/navbar.j2 @@ -0,0 +1,8 @@ + +