Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | 1310x 1310x 1310x 1x 1x 1309x 1309x 1310x 902x 407x 1310x 1310x 306x 407x | import { defaults } from "./defaults.ts";
import type { GrayMatterFile, GrayMatterOptions } from "./types.ts";
import { getStringProp, isString } from "./utils.ts";
/**
* Extract excerpt from file content
*/
export function excerpt(file: GrayMatterFile, options?: GrayMatterOptions): GrayMatterFile {
const opts = defaults(options);
// Ensure data is an object (defensive check for external callers)
file.data ??= {};
if (typeof opts.excerpt === "function") {
opts.excerpt(file, opts);
return file;
}
const dataSep = getStringProp(file.data, "excerpt_separator");
const sep = dataSep !== "" ? dataSep : opts.excerpt_separator;
if (sep == null && (opts.excerpt === false || opts.excerpt == null)) {
return file;
}
const delimiter = isString(opts.excerpt) ? opts.excerpt : (sep ?? opts.delimiters[0]);
// if enabled, get the excerpt defined after front-matter
const idx = file.content.indexOf(delimiter);
if (idx !== -1) {
file.excerpt = file.content.slice(0, idx);
}
return file;
}
if (import.meta.vitest) {
const { fc, test } = await import("@fast-check/vitest");
const makeFile = (content: string, data: Record<string, unknown> = {}): GrayMatterFile => ({
content,
data,
excerpt: "",
orig: new TextEncoder().encode(content),
language: "yaml",
matter: "",
isEmpty: false,
stringify: () => "",
});
describe("excerpt", () => {
it("should extract excerpt using default delimiter", () => {
const file = makeFile("This is excerpt\n---\nThis is content");
const result = excerpt(file, { excerpt: true });
expect(result.excerpt).toBe("This is excerpt\n");
});
it("should extract excerpt using custom string delimiter", () => {
const file = makeFile("This is excerpt\n<!-- more -->\nThis is content");
const result = excerpt(file, { excerpt: "<!-- more -->" });
expect(result.excerpt).toBe("This is excerpt\n");
});
it("should use excerpt_separator from options", () => {
const file = makeFile("Excerpt here\n***\nContent here");
const result = excerpt(file, { excerpt: true, excerpt_separator: "***" });
expect(result.excerpt).toBe("Excerpt here\n");
});
it("should use excerpt_separator from file.data", () => {
const file = makeFile("Excerpt\n<!-- end -->\nContent", {
excerpt_separator: "<!-- end -->",
});
const result = excerpt(file, { excerpt: true });
expect(result.excerpt).toBe("Excerpt\n");
});
it("should not extract when excerpt is false", () => {
const file = makeFile("Some content\n---\nMore content");
const result = excerpt(file, { excerpt: false });
expect(result.excerpt).toBe("");
});
it("should not modify when delimiter not found", () => {
const file = makeFile("No delimiter here");
const result = excerpt(file, { excerpt: true });
expect(result.excerpt).toBe("");
});
it("should call custom excerpt function", () => {
const file = makeFile("Custom content");
const customFn = vi.fn((f: GrayMatterFile) => {
f.excerpt = "Custom excerpt";
});
const result = excerpt(file, { excerpt: customFn });
expect(customFn).toHaveBeenCalledOnce();
expect(result.excerpt).toBe("Custom excerpt");
});
it("should initialize file.data if null", () => {
const file = makeFile("content");
file.data = null as unknown as Record<string, unknown>;
const result = excerpt(file, {});
expect(result.data).toEqual({});
});
test.prop([
fc.string({ minLength: 1, maxLength: 50 }),
fc.string({ minLength: 1, maxLength: 50 }),
])("should extract correct excerpt when delimiter exists", (excerptText, contentText) => {
const delimiter = "---";
const content = `${excerptText}\n${delimiter}\n${contentText}`;
const file = makeFile(content);
const result = excerpt(file, { excerpt: true });
expect(result.excerpt).toBe(`${excerptText}\n`);
});
test.prop([fc.string({ minLength: 1, maxLength: 100 })])(
"should not extract when no delimiter in content",
(content) => {
const safeContent = content.replace(/---/g, "___");
const file = makeFile(safeContent);
const result = excerpt(file, { excerpt: true });
expect(result.excerpt).toBe("");
},
);
test.prop([
fc.string({ minLength: 1, maxLength: 20 }),
fc.string({ minLength: 1, maxLength: 20 }),
fc
.string({ minLength: 1, maxLength: 10 })
.filter((s) => !s.includes("\n") && !/[[\]{}()*+?.,\\^$|#]/.test(s)),
])("should work with any custom delimiter", (excerptText, contentText, customDelimiter) => {
const safeExcerpt = excerptText.replaceAll(customDelimiter, "");
if (safeExcerpt === "") return;
const content = `${safeExcerpt}\n${customDelimiter}\n${contentText}`;
const file = makeFile(content);
const result = excerpt(file, { excerpt: customDelimiter });
expect(result.excerpt).toBe(`${safeExcerpt}\n`);
});
});
}
|