matter-json
Version:
JSON front-matter parser and combiner. Minimal and perfect
126 lines (113 loc) • 3.98 kB
JavaScript
/* *******************************************************
* matter-json
*
* @license
*
* Apache-2.0
*
* Copyright 2014-2025 Alex Stevovich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @meta
*
* package_name: matter-json
* file_name: src/index.js
* purpose: Core functionality and exports combined.
*
* @system
*
* generated_on: 2025-03-15T03:23:29.849Z
* certified_version: 1.0.0
* file_uuid: 08ec44c1-3a6e-46bf-ae2c-248a4f6fa552
* file_size: 3983 bytes
* file_hash: 72a029c1db8b8c407277ada960db9fb690527afa3b9356a01ed9657f3c024d23
* mast_hash: e44be86c2b436cc12973c50f3dc8ce64b765efdce69803e85a138a96c84e7bc5
* generated_by: preamble on npm!
*
* [Preamble Metadata]
********************************************************/
const FRONT_MATTER_REGEX = /^---\s*\n([\s\S]+?)\n---\s*(?:\n([\s\S]*))?$/;
/**
* Parses JSON front matter and returns the extracted data and content.
* @param {string} text - The full content containing front matter and content.
* @returns {{ data: object, content: string }} - The parsed front matter and content.
* @throws {TypeError} - If the input is not a string.
* @throws {Error} - If the front matter format is invalid or JSON parsing fails.
*/
export function parse(text) {
if (typeof text !== 'string') {
throw new TypeError(
`parse expected a string, but received ${typeof text}.`,
);
}
const match = text.match(FRONT_MATTER_REGEX);
if (!match) {
throw new Error(
`Invalid front matter format. Ensure it is wrapped with "---" and is valid JSON.`,
);
}
try {
const data = JSON.parse(match[1]);
return { data, content: match[2] || '' };
} catch (error) {
throw new Error(`JSON Parsing Error: ${error.message}`);
}
}
/**
* Serializes data and content into a formatted JSON front matter string.
* @param {object} data - The front matter object.
* @param {string} content - The document content.
* @param {number} [indentation=2] - Optional JSON indentation level.
* @returns {string} - The serialized front matter and content.
* @throws {TypeError} - If data is not an object or content is not a string.
*/
export function serialize(data, content, indentation = 2) {
if (typeof data !== 'object' || data === null) {
throw new TypeError(
`serialize expected an object, but received ${typeof data}.`,
);
}
if (typeof content !== 'string') {
throw new TypeError(
`serialize expected a string, but received ${typeof content}.`,
);
}
try {
const frontMatter = JSON.stringify(data, null, indentation).trim();
return `---\n${frontMatter}\n---\n${content}`;
} catch (error) {
throw new Error(`JSON Serialization Error: ${error.message}`);
}
}
/**
* Validates whether a given text has properly formatted front matter and parsable JSON.
* @param {string} text - The full document to validate.
* @returns {boolean} - `true` if the format is valid and JSON is parsable, otherwise `false`.
*/
export function validate(text) {
if (typeof text !== 'string') {
return false;
}
const match = text.match(FRONT_MATTER_REGEX);
if (!match) {
return false;
}
try {
JSON.parse(match[1]); // Validate JSON
return true;
} catch {
return false; // Invalid JSON
}
}
export default { parse, serialize, validate };