Skip to content

Commit

Permalink
encoding: add front matter module (denoland#2335)
Browse files Browse the repository at this point in the history
Co-authored-by: Yoshiya Hinosawa <[email protected]>
  • Loading branch information
littledivy and kt3k committed Jun 14, 2022
1 parent a06298b commit 6dbb212
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 0 deletions.
63 changes: 63 additions & 0 deletions encoding/front_matter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
// Copyright (c) Jason Campbell. MIT license.
// https://github.com/jxson/front-matter/blob/36f139ef797bd9e5196a9ede03ef481d7fbca18e/index.js

import { parse } from "./yaml.ts";

const pattern = "^(" +
"\\ufeff?" + // Maybe byte order mark
"(= yaml =|---)" +
"$([\\s\\S]*?)" +
"^(?:\\2|\\.\\.\\.)\\s*" +
"$" +
(Deno.build.os === "windows" ? "\\r?" : "") +
"(?:\\n)?)";
const regex = new RegExp(pattern, "m");

export type Extract<T> = {
frontMatter: string;
body: string;
attrs: T;
};

/**
* Extracts front matter from a string.
* @param str String to extract from.
*
* ```ts
* import { extract } from "https://deno.land/std@$STD_VERSION/encoding/front_matter.ts";
* import { assertEquals } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* const { attrs, body, frontMatter } = extract<{ title: string }>("---\ntitle: Three dashes marks the spot\n---\n");
* assertEquals(attrs.title, "Three dashes marks the spot");
* assertEquals(body, "");
* assertEquals(frontMatter, "---\ntitle: Three dashes marks the spot\n---\n");
* ```
*/
export function extract<T = unknown>(str: string): Extract<T> {
const lines = str.split(/(\r?\n)/);
if (/= yaml =|---/.test(lines[0])) {
const match = regex.exec(str);
if (!match) throw new TypeError("Unexpected end of input");
const frontMatter = match.at(-1)?.replace(/^\s+|\s+$/g, "") || "";
const attrs = parse(frontMatter) as T;
const body = str.replace(match[0], "");
return { frontMatter, body, attrs };
}
throw new TypeError("Failed to extract front matter");
}

/**
* Tests if a string has valid front matter.
* @param str String to test.
*
* ```ts
* import { test } from "https://deno.land/std@$STD_VERSION/encoding/front_matter.ts";
* import { assert } from "https://deno.land/std@$STD_VERSION/testing/asserts.ts";
*
* assert(test("---\ntitle: Three dashes marks the spot\n---\n"));
* ```
*/
export function test(str: string): boolean {
return regex.test(str);
}
77 changes: 77 additions & 0 deletions encoding/front_matter_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.

import { extract, test } from "./front_matter.ts";
import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";

Deno.test("test valid input true", () => {
[
"---\nname: deno\n---\n",
"= yaml =\nname: deno\n= yaml =\n",
"= yaml =\nname: deno\n= yaml =\ndeno is awesome\n",
].forEach((str) => {
assert(test(str));
});
});

Deno.test("test invalid input false", () => {
[
"",
"---",
"= yaml =",
"---\n",
"= yaml =\n",
"---\nasdasdasd",
].forEach((str) => {
assert(!test(str));
});
});

Deno.test("extract type error on invalid input", () => {
[
"",
"---",
"= yaml =",
"---\n",
"= yaml =\n",
"---\nasdasdasd",
].forEach((str) => {
assertThrows(() => extract(str), TypeError);
});
});

Deno.test("parse yaml delinetead by `---`", () => {
const content = extract<
{ title: string; tags: string[]; "expaned-description": string }
>(`---
title: Three dashes marks the spot
tags:
- yaml
- front-matter
- dashes
expaned-description: with some --- crazy stuff in it
---
don't break
---
Also this shouldn't be a problem
`);
assert(content !== undefined);
assertEquals(
content.frontMatter,
`title: Three dashes marks the spot
tags:
- yaml
- front-matter
- dashes
expaned-description: with some --- crazy stuff in it`,
);
assertEquals(
content.body,
"don't break\n---\nAlso this shouldn't be a problem\n",
);
assertEquals(content.attrs.title, "Three dashes marks the spot");
assertEquals(content.attrs.tags, ["yaml", "front-matter", "dashes"]);
assertEquals(
content.attrs["expaned-description"],
"with some --- crazy stuff in it",
);
});

0 comments on commit 6dbb212

Please sign in to comment.