feat(git): README des Repositories holen
Erspart den Wechsel ins Git, nur um zu sehen, worum ein halbvergessenes Projekt eigentlich ging. GitHub hat einen eigenen Endpunkt, der jede Schreibweise findet - ein Aufruf genuegt. GitLab und Gitea kennen keinen; dort wird erst das Wurzelverzeichnis aufgelistet und dann die gefundene Datei geholt. Erkannt werden README.md und die ueblichen Varianten, Gross- und Kleinschreibung egal; Markdown hat Vorrang, weil nur das wirklich dargestellt werden kann. Geholt wird hoechstens einmal am Tag, wie der Kalender, und mit eigenem Zeitstempel: schlaegt das eine fehl, soll das andere nicht mit blockiert werden. Bei 60 000 Zeichen wird abgeschnitten, aber an einer Zeilengrenze - sonst bliebe womoeglich ein halber Codeblock stehen. Dekodiert wird ueber Buffer und nicht ueber atob, sonst kaemen Umlaute als Kauderwelsch heraus. Kein README ist eine Auskunft, kein Fehlschlag: der Zeitstempel wird dann trotzdem gesetzt, damit nicht jeder Abgleich erneut sucht. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { README_MAX_CHARS, capReadme, decodeBase64, pickReadme } from "./readme";
|
||||
|
||||
describe("pickReadme", () => {
|
||||
it("findet die uebliche Schreibweise", () => {
|
||||
expect(pickReadme(["src", "README.md", "package.json"])).toBe("README.md");
|
||||
});
|
||||
|
||||
it("ist bei der Gross- und Kleinschreibung nachsichtig", () => {
|
||||
expect(pickReadme(["readme.md"])).toBe("readme.md");
|
||||
expect(pickReadme(["ReadMe.MD"])).toBe("ReadMe.MD");
|
||||
});
|
||||
|
||||
it("zieht Markdown den uebrigen Formaten vor", () => {
|
||||
// Beides kommt vor; nur das erste laesst sich wirklich darstellen.
|
||||
expect(pickReadme(["README.rst", "README.md"])).toBe("README.md");
|
||||
});
|
||||
|
||||
it("nimmt auch ein README ohne Endung", () => {
|
||||
expect(pickReadme(["LICENSE", "README"])).toBe("README");
|
||||
});
|
||||
|
||||
it("liefert null, wenn keines dabei ist", () => {
|
||||
expect(pickReadme(["src", "package.json"])).toBeNull();
|
||||
expect(pickReadme([])).toBeNull();
|
||||
});
|
||||
|
||||
it("verwechselt Aehnliches nicht mit dem README", () => {
|
||||
expect(pickReadme(["README-CONTRIBUTING.md", "readme.md.bak"])).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("capReadme", () => {
|
||||
it("laesst Kurzes unangetastet", () => {
|
||||
const { content, truncated } = capReadme("# Titel\n\nEin Satz.");
|
||||
expect(content).toBe("# Titel\n\nEin Satz.");
|
||||
expect(truncated).toBe(false);
|
||||
});
|
||||
|
||||
it("kuerzt Langes an einer Zeilengrenze", () => {
|
||||
// Sonst bliebe womoeglich ein halber Codeblock stehen.
|
||||
const zeile = "x".repeat(80);
|
||||
const lang = Array.from({ length: 2000 }, () => zeile).join("\n");
|
||||
const { content, truncated } = capReadme(lang);
|
||||
expect(truncated).toBe(true);
|
||||
expect(content.length).toBeLessThanOrEqual(README_MAX_CHARS);
|
||||
expect(content.endsWith("x")).toBe(true);
|
||||
expect(content.split("\n").at(-1)).toBe(zeile);
|
||||
});
|
||||
|
||||
it("kuerzt notfalls hart, wenn es gar keine Zeilengrenze gibt", () => {
|
||||
// Eine einzige riesige Zeile: hier waere der letzte Umbruch bei -1.
|
||||
const { content, truncated } = capReadme("y".repeat(README_MAX_CHARS + 500));
|
||||
expect(truncated).toBe(true);
|
||||
expect(content).toHaveLength(README_MAX_CHARS);
|
||||
});
|
||||
});
|
||||
|
||||
describe("decodeBase64", () => {
|
||||
it("dekodiert UTF-8 richtig", () => {
|
||||
// Ueber Bytes gedacht kaeme hier Kauderwelsch heraus.
|
||||
const kodiert = Buffer.from("# Nebula – Übersicht", "utf8").toString("base64");
|
||||
expect(decodeBase64(kodiert)).toBe("# Nebula – Übersicht");
|
||||
});
|
||||
|
||||
it("uebergeht Zeilenumbrueche in der Kodierung", () => {
|
||||
// GitHub bricht den base64-Block alle 60 Zeichen um.
|
||||
const roh = Buffer.from("Hallo Welt", "utf8").toString("base64");
|
||||
const umgebrochen = `${roh.slice(0, 4)}\n${roh.slice(4)}`;
|
||||
expect(decodeBase64(umgebrochen)).toBe("Hallo Welt");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user