From 1bb2b56366cad44509bf201d6845130e54522fc9 Mon Sep 17 00:00:00 2001 From: Caleb Date: Mon, 30 Oct 2017 13:48:19 -0600 Subject: [PATCH] Cleanup file formatters. (#759) * Clean up frontmatter formatter. * Move `formatToExtension`. * Use plain objects for file formatters. * Use same parsers for files and frontmatter. We want to use our file parsers for frontmatter, instead of the builtin ones, as they process some formats (images, dates) properly. * Cleanup YAML frontmatter parser code. --- src/formats/__tests__/frontmatter.spec.js | 4 +- src/formats/formats.js | 19 ++++++---- src/formats/frontmatter.js | 46 ++++++++++------------- src/formats/json.js | 4 +- src/formats/toml.js | 4 +- src/formats/yaml.js | 4 +- src/reducers/collections.js | 9 +---- 7 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/formats/__tests__/frontmatter.spec.js b/src/formats/__tests__/frontmatter.spec.js index 6c7e0e1b..9a9c26eb 100644 --- a/src/formats/__tests__/frontmatter.spec.js +++ b/src/formats/__tests__/frontmatter.spec.js @@ -1,9 +1,7 @@ -import Frontmatter from '../frontmatter'; +import FrontmatterFormatter from '../frontmatter'; jest.mock("../../valueObjects/AssetProxy.js"); -const FrontmatterFormatter = new Frontmatter(); - describe('Frontmatter', () => { it('should parse YAML with --- delimiters', () => { expect( diff --git a/src/formats/formats.js b/src/formats/formats.js index d529323a..267aa24b 100644 --- a/src/formats/formats.js +++ b/src/formats/formats.js @@ -1,12 +1,15 @@ -import YAML from './yaml'; -import TOML from './toml'; -import JSONFormatter from './json'; -import Frontmatter from './frontmatter'; +import yamlFormatter from './yaml'; +import tomlFormatter from './toml'; +import jsonFormatter from './json'; +import FrontmatterFormatter from './frontmatter'; -const yamlFormatter = new YAML(); -const tomlFormatter = new TOML(); -const jsonFormatter = new JSONFormatter(); -const FrontmatterFormatter = new Frontmatter(); +export const formatToExtension = format => ({ + markdown: 'md', + yaml: 'yml', + toml: 'toml', + json: 'json', + html: 'html', +}[format]); function formatByType(type) { // Right now the only type is "editorialWorkflow" and diff --git a/src/formats/frontmatter.js b/src/formats/frontmatter.js index 251a99d9..620ee090 100644 --- a/src/formats/frontmatter.js +++ b/src/formats/frontmatter.js @@ -1,12 +1,11 @@ import matter from 'gray-matter'; -import TOML from './toml'; -import YAML from './yaml'; - -const tomlFormatter = new TOML(); +import tomlFormatter from './toml'; +import yamlFormatter from './yaml'; +import jsonFormatter from './json'; const parsers = { - toml: tomlFormatter.fromFile.bind(tomlFormatter), - json: (input) => { + toml: input => tomlFormatter.fromFile(input), + json: input => { let JSONinput = input.trim(); // Fix JSON if leading and trailing brackets were trimmed. if (JSONinput.substr(0, 1) !== '{') { @@ -15,7 +14,11 @@ const parsers = { if (JSONinput.substr(-1) !== '}') { JSONinput = JSONinput + '}'; } - return matter.engines.json.parse(JSONinput); + return jsonFormatter.fromFile(JSONinput); + }, + yaml: { + parse: input => yamlFormatter.fromFile(input), + stringify: (metadata, { sortedKeys }) => yamlFormatter.toFile(metadata, sortedKeys), }, } @@ -37,31 +40,20 @@ function inferFrontmatterFormat(str) { } } -export default class Frontmatter { +export default { fromFile(content) { const result = matter(content, { engines: parsers, ...inferFrontmatterFormat(content) }); - const data = result.data; - data.body = result.content; - return data; - } + return { + ...result.data, + body: result.content, + }; + }, toFile(data, sortedKeys) { - const meta = {}; - let body = ''; - Object.keys(data).forEach((key) => { - if (key === 'body') { - body = data[key]; - } else { - meta[key] = data[key]; - } - }); + const { body, ...meta } = data; // always stringify to YAML - const parser = { - stringify(metadata) { - return new YAML().toFile(metadata, sortedKeys); - }, - }; - return matter.stringify(body, meta, { language: "yaml", delimiters: "---", engines: { yaml: parser } }); + // `sortedKeys` is not recognized by gray-matter, so it gets passed through to the parser + return matter.stringify(body, meta, { engines: parsers, language: "yaml", delimiters: "---", sortedKeys }); } } diff --git a/src/formats/json.js b/src/formats/json.js index e2e5467e..ff13771c 100644 --- a/src/formats/json.js +++ b/src/formats/json.js @@ -1,7 +1,7 @@ -export default class JSONFormatter { +export default { fromFile(content) { return JSON.parse(content); - } + }, toFile(data) { return JSON.stringify(data); diff --git a/src/formats/toml.js b/src/formats/toml.js index 4255c685..45e6a2ec 100644 --- a/src/formats/toml.js +++ b/src/formats/toml.js @@ -15,10 +15,10 @@ const outputReplacer = (key, value) => { return false; }; -export default class TOML { +export default { fromFile(content) { return toml.parse(content); - } + }, toFile(data, sortedKeys = []) { return tomlify.toToml(data, { replace: outputReplacer, sort: sortKeys(sortedKeys) }); diff --git a/src/formats/yaml.js b/src/formats/yaml.js index fec213a7..d471c337 100644 --- a/src/formats/yaml.js +++ b/src/formats/yaml.js @@ -36,10 +36,10 @@ const OutputSchema = new yaml.Schema({ explicit: yaml.DEFAULT_SAFE_SCHEMA.explicit, }); -export default class YAML { +export default { fromFile(content) { return yaml.safeLoad(content); - } + }, toFile(data, sortedKeys = []) { return yaml.safeDump(data, { schema: OutputSchema, sortKeys: sortKeys(sortedKeys) }); diff --git a/src/reducers/collections.js b/src/reducers/collections.js index 25d913fe..4c0bf1c0 100644 --- a/src/reducers/collections.js +++ b/src/reducers/collections.js @@ -4,6 +4,7 @@ import consoleError from '../lib/consoleError'; import { CONFIG_SUCCESS } from '../actions/config'; import { FILES, FOLDER } from '../constants/collectionTypes'; import { INFERABLE_FIELDS } from '../constants/fieldInference'; +import { formatToExtension } from '../formats/formats'; const collections = (state = null, action) => { const configCollections = action.payload && action.payload.collections; @@ -26,14 +27,6 @@ const collections = (state = null, action) => { } }; -const formatToExtension = format => ({ - markdown: 'md', - yaml: 'yml', - toml: 'toml', - json: 'json', - html: 'html', -}[format]); - const selectors = { [FOLDER]: { entryExtension(collection) {