123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- 'use strict';
- const yaml = require('js-yaml');
- const rPrefixSep = /^(-{3,}|;{3,})/;
- const rFrontMatter = /^(-{3,}|;{3,})\n([\s\S]+?)\n\1\n?([\s\S]*)/;
- const rFrontMatterNew = /^([\s\S]+?)\n(-{3,}|;{3,})\n?([\s\S]*)/;
- function split(str) {
- if (typeof str !== 'string') throw new TypeError('str is required!');
- const matchOld = str.match(rFrontMatter);
- if (matchOld) {
- return {
- data: matchOld[2],
- content: matchOld[3] || '',
- separator: matchOld[1],
- prefixSeparator: true
- };
- }
- if (rPrefixSep.test(str)) return { content: str };
- const matchNew = str.match(rFrontMatterNew);
- if (matchNew) {
- return {
- data: matchNew[1],
- content: matchNew[3] || '',
- separator: matchNew[2],
- prefixSeparator: false
- };
- }
- return { content: str };
- }
- function parse(str, options) {
- if (typeof str !== 'string') throw new TypeError('str is required!');
- const splitData = split(str);
- const raw = splitData.data;
- if (!raw) return { _content: str };
- let data;
- if (splitData.separator.startsWith(';')) {
- data = parseJSON(raw);
- } else {
- data = parseYAML(raw, options);
- }
- if (!data) return { _content: str };
- // Convert timezone
- Object.keys(data).forEach(key => {
- const item = data[key];
- if (item instanceof Date) {
- data[key] = new Date(item.getTime() + (item.getTimezoneOffset() * 60 * 1000));
- }
- });
- data._content = splitData.content;
- return data;
- }
- function parseYAML(str, options) {
- const result = yaml.load(escapeYAML(str), options);
- if (typeof result !== 'object') return;
- return result;
- }
- function parseJSON(str) {
- try {
- return JSON.parse(`{${str}}`);
- } catch (err) {
- return; // eslint-disable-line
- }
- }
- function escapeYAML(str) {
- if (typeof str !== 'string') throw new TypeError('str is required!');
- return str.replace(/\n(\t+)/g, (match, tabs) => {
- let result = '\n';
- for (let i = 0, len = tabs.length; i < len; i++) {
- result += ' ';
- }
- return result;
- });
- }
- function stringify(obj, options = {}) {
- if (!obj) throw new TypeError('obj is required!');
- const { _content: content = '' } = obj;
- delete obj._content;
- if (!Object.keys(obj).length) return content;
- const { mode, prefixSeparator } = options;
- const separator = options.separator || (mode === 'json' ? ';;;' : '---');
- let result = '';
- if (prefixSeparator) result += `${separator}\n`;
- if (mode === 'json') {
- result += stringifyJSON(obj);
- } else {
- result += stringifyYAML(obj, options);
- }
- result += `${separator}\n${content}`;
- return result;
- }
- function stringifyYAML(obj, options) {
- const keys = Object.keys(obj);
- const data = {};
- const nullKeys = [];
- const dateKeys = [];
- let key, value, i, len;
- for (i = 0, len = keys.length; i < len; i++) {
- key = keys[i];
- value = obj[key];
- if (value == null) {
- nullKeys.push(key);
- } else if (value instanceof Date) {
- dateKeys.push(key);
- } else {
- data[key] = value;
- }
- }
- let result = yaml.dump(data, options);
- if (dateKeys.length) {
- for (i = 0, len = dateKeys.length; i < len; i++) {
- key = dateKeys[i];
- result += `${key}: ${formatDate(obj[key])}\n`;
- }
- }
- if (nullKeys.length) {
- for (i = 0, len = nullKeys.length; i < len; i++) {
- result += `${nullKeys[i]}:\n`;
- }
- }
- return result;
- }
- function stringifyJSON(obj) {
- return JSON.stringify(obj, null, ' ')
- // Remove indention
- .replace(/\n {2}/g, () => '\n')
- // Remove prefixing and trailing braces
- .replace(/^{\n|}$/g, '');
- }
- function doubleDigit(num) {
- return num.toString().padStart(2, '0');
- }
- function formatDate(date) {
- return `${date.getFullYear()}-${doubleDigit(date.getMonth() + 1)}-${doubleDigit(date.getDate())} ${doubleDigit(date.getHours())}:${doubleDigit(date.getMinutes())}:${doubleDigit(date.getSeconds())}`;
- }
- module.exports = {
- parse,
- split,
- escape: escapeYAML,
- stringify
- };
|