From 95692cf5540f1c0777ec08464ad5cc2a420406d6 Mon Sep 17 00:00:00 2001 From: Asko Nõmm Date: Tue, 28 Jan 2025 21:29:22 +0200 Subject: Improve docs, namings --- src/flatmatter.test.ts | 41 ++- src/flatmatter.ts | 654 ++++++++++++++++++-------------------- src/serializers/to_json.test.ts | 12 +- src/serializers/to_json.ts | 6 +- src/serializers/to_object.test.ts | 31 +- src/serializers/to_object.ts | 8 +- src/utils.ts | 4 - 7 files changed, 361 insertions(+), 395 deletions(-) (limited to 'src') diff --git a/src/flatmatter.test.ts b/src/flatmatter.test.ts index bbe26d9..9f00ef9 100644 --- a/src/flatmatter.test.ts +++ b/src/flatmatter.test.ts @@ -1,22 +1,33 @@ import FlatMatter from "./flatmatter.ts"; -import {assert} from "vitest"; +import { assert } from "vitest"; import ToObject from "./serializers/to_object.ts"; -test('Line has no value separator', () => { - assert.throws(() => new FlatMatter('test'), "Line on index 0 doesn't have a value separator."); -}) +test("Line has no value separator", () => { + assert.throws( + () => new FlatMatter("test"), + "Line on index 0 doesn't have a value separator." + ); +}); -test('Line can only have one value separator', () => { - assert.throws(() => new FlatMatter('test: this: that'), 'Line on index 0 has multiple value separators.') -}) +test("Line can only have one value separator", () => { + assert.throws( + () => new FlatMatter("test: this: that"), + "Line on index 0 has multiple value separators." + ); +}); -test('String values can have colon characters', () => { - assert.doesNotThrow(() => new FlatMatter('test: "this : that"'), Error) -}) +test("String values can have colon characters", () => { + assert.doesNotThrow(() => new FlatMatter('test: "this : that"'), Error); +}); -test('FrontMatter creates a new content entry', () => { - const fm = new FlatMatter(`---\nthis: true\n---\n\nMarkdown goes here.\n\nAnd here.`); - const result = fm.serialize(new ToObject()); +test("FrontMatter creates a new content entry", () => { + const fm = new FlatMatter( + `---\nthis: true\n---\n\nMarkdown goes here.\n\nAnd here.` + ); + const result = fm.serialize(new ToObject()); - assert.deepEqual(result, {"this": true, "content": "Markdown goes here.\n\nAnd here."}); -}) \ No newline at end of file + assert.deepEqual(result, { + this: true, + content: "Markdown goes here.\n\nAnd here.", + }); +}); diff --git a/src/flatmatter.ts b/src/flatmatter.ts index 8ffee6f..e81df1f 100644 --- a/src/flatmatter.ts +++ b/src/flatmatter.ts @@ -1,401 +1,355 @@ import { EOL } from "node:os"; -import {trimChar} from "./utils.ts"; +import { trimChar } from "./utils.ts"; export type ParsedValue = { - value: unknown; - computeActions: ComputeAction[]; + value: unknown; + computeActions: ComputeAction[]; }; export type ComputeAction = { - identifier: string; - args: Array; + identifier: string; + args: Array; }; -export interface Serializer { - serialize(parsedConfig: Record): unknown; +export interface Serializer { + serialize(config: Record): T; } export interface FlatMatterFn { - name: string; + name: string; - compute(...args: unknown[]): unknown; + compute(...args: unknown[]): unknown; } export default class FlatMatter { - private content: string; - private parsedConfig: Record = {}; - private functions: FlatMatterFn[]; - - constructor(content: string, functions: FlatMatterFn[] = []) { - this.content = content; - this.functions = functions; - this.parse(); + private content: string; + private parsedConfig: Record = {}; + private functions: FlatMatterFn[]; + + constructor(content: string, functions: FlatMatterFn[] = []) { + this.content = content; + this.functions = functions; + this.parse(); + } + + private parse(): void { + const lines = this.content.split(EOL); + let frontMatterBreakCount = 0; + + for (let i = 0; i < lines.length; i++) { + if (lines[i].trim() === "---" && frontMatterBreakCount < 2) { + frontMatterBreakCount++; + continue; + } + + // FlatMatter ends, Markdown begins + if (frontMatterBreakCount < 2) { + this.parseLine(i, lines[i]); + continue; + } + + this.parsedConfig.content = lines.slice(i).join(EOL).trim(); + break; } - - private parse(): void { - const lines = this.content.split(/\r?\n/); - let frontMatterBreakCount = 0; - - for (let i = 0; i < lines.length; i++) { - if (lines[i].trim() === "---" && frontMatterBreakCount < 2) { - frontMatterBreakCount++; - continue; - } - - - // FlatMatter ends, Markdown begins - if (frontMatterBreakCount < 2) { - this.parseLine(i, lines[i]); - continue; - } - - this.parsedConfig.content = lines.slice(i).join(EOL).trim(); - break; - } + } + + /** + * Parses a given line of FlatMatter. + */ + private parseLine(idx: number, line: string): void { + this.validateLineConformance(idx, line); + + const keys = line.split(":")[0].trim().split("."); + const value = line.split(":").slice(1).join(":").trim(); + const parsedValue = this.parseValue(value); + + if (!parsedValue) return; + + const config = keys.reduceRight((acc, key) => { + return { [key]: acc }; + }, this.computeValue(parsedValue)) as Record; + + this.parsedConfig = { ...this.parsedConfig, ...config }; + } + + /** + * For better developer experience, this validates each line + * against some common mistakes you can make, and throws an Error + * if you did. + */ + private validateLineConformance(idx: number, line: string): void { + const validators = [ + this.validateLineHasKeyVal, + this.validateLineHasOnlyOneColonChar, + ]; + + for (const validator of validators) { + validator(idx, line); + } + } + + /** + * Validates that the given line has a value separator. + */ + private validateLineHasKeyVal(idx: number, line: string): void { + if (!line.includes(":")) { + throw new Error(`Line on index ${idx} doesn't have a value separator.`); + } + } + + /** + * Validates that the given line has only one value separator. + */ + private validateLineHasOnlyOneColonChar(idx: number, line: string): void { + let separatorCount = 0; + let parts = line.split(":").slice(1); + + for (let i = 0; i < parts.length; i++) { + const partsUntilCurrent = parts.slice(0, i).join(":"); + const quoteCount = partsUntilCurrent.split('"').length - 1; + + if (quoteCount % 2 === 0) { + separatorCount++; + } } - /** - * Parses a given line of FlatMatter. - * - * @param idx - * @param {string} line - */ - private parseLine(idx: number, line: string): void { - this.validateLineConformance(idx, line); + if (separatorCount > 1) { + throw new Error(`Line on index ${idx} has multiple value separators.`); + } + } + + /** + * Detects if the value is a simple value. A simple value is any + * of the following: `"a string"`, boolean `true` or `false`, or + * anything numeric like `12345` or `123.45`. + */ + private isSimpleValue(value: string): boolean { + const isString = value.startsWith('"') && value.endsWith('"'); + const isBoolean = value === "true" || value === "false"; + const isNumber = !isNaN(parseFloat(value)); + + return isString || isBoolean || isNumber; + } + + /** + * Detects if the value is a function value. A function value is any + * of the following: + * + * - A function call with arguments: `(function-name *args)` + * - A function call by reference: `function-name` + */ + private isFunctionValue(value: string): boolean { + const isFnCall = value.startsWith("(") && value.endsWith(")"); + const isFnReference = !!value.match(/^([a-zA-Z0-9_-]+)$/); + + return isFnCall || isFnReference; + } + + /** + * Detects if the value is a piped value. A piped value is a mix of + * simple and function value parts, piped together with the forward + * slash `/` character. For example: + * + * ```yaml + * posts: (get-content "posts") / (limit 10) / only-published + * ``` + * + * or: + * + * ```yaml + * posts: "posts" / get-content / (limit 10) / only-published + * ``` + * + * The result of the previous pipe gets passed to the next as a first + * argument. + */ + private isPipedValue(value: string): boolean { + return this.composePipedValueParts(value).every((part) => { + return this.isSimpleValue(part) || this.isFunctionValue(part); + }); + } + + /** + * Parses a value to a `ParsedValue` object, or `null` + * in case it could not for whatever reason. + */ + private parseValue(value: string): ParsedValue | null { + if (this.isSimpleValue(value)) { + return { + value: this.parseSimpleValue(value), + computeActions: [], + }; + } - const keys = line.split(":")[0].trim().split("."); - const value = line.split(":").slice(1).join(":").trim(); - const parsedValue = this.parseValue(value); + if (this.isFunctionValue(value)) { + return { + value: null, + computeActions: [this.parseFunctionValue(value)], + }; + } - if (!parsedValue) return; + if (this.isPipedValue(value)) { + return this.parsePipedValue(value); + } - const config = keys.reduceRight((acc, key) => { - return {[key]: acc}; - }, this.computeValue(parsedValue)) as Record; + return null; + } - this.parsedConfig = {...this.parsedConfig, ...config}; + /** + * Parses the value part of a line into a simple value, like for example + * a `string`, `number` or `boolean`. + */ + private parseSimpleValue(value: string): string | number | boolean { + if (value === "true" || value === "false") { + return value === "true"; } - /** - * For better developer experience, this validates each line - * against some common mistakes you can make, and throws an Error - * if you did. - * - * @param {number} idx - * @param {string} line - */ - private validateLineConformance(idx: number, line: string): void { - const validators = [ - this.validateLineHasKeyVal, - this.validateLineHasOnlyOneColonChar, - ]; - - for(const validator of validators) { - validator(idx, line); - } + if (!Number.isNaN(parseInt(value)) && value.indexOf(".") === -1) { + return parseInt(value); } - /** - * Validates that the given line has a value separator. - * - * @param {number} idx - * @param {string} line - */ - private validateLineHasKeyVal(idx: number, line: string): void { - if (!line.includes(":")) { - throw new Error(`Line on index ${idx} doesn't have a value separator.`); - } + if (!Number.isNaN(parseFloat(value)) && value.indexOf(".") !== -1) { + return parseFloat(value); } - /** - * Validates that the given line has only one value separator. - * - * @param {number} idx - * @param {string} line - */ - private validateLineHasOnlyOneColonChar(idx: number, line: string): void { - let separatorCount = 0; - let parts = line.split(":").slice(1); - - for(let i = 0; i < parts.length; i++) { - const partsUntilCurrent = parts.slice(0, i).join(":"); - const quoteCount = partsUntilCurrent.split('"').length - 1; - - if (quoteCount % 2 === 0) { - separatorCount++; - } - } - - if (separatorCount > 1) { - throw new Error(`Line on index ${idx} has multiple value separators.`); - } + return trimChar(value, '"'); + } + + /** + * Parses the value part of a line into a Compute Action, which is + * later executed to run the function described in FlatMatter. + */ + private parseFunctionValue(value: string): ComputeAction { + const isFn = value.startsWith("(") && value.endsWith(")"); + + if (!isFn) { + return { + identifier: value, + args: [], + }; } - /** - * Detects if the value is a simple value. A simple value is any - * of the following: `"a string"`, boolean `true` or `false`, or - * anything numeric like `12345` or `123.45`. - * - * @param {string} value - * @returns {boolean} - */ - private isSimpleValue(value: string): boolean { - const isString = value.startsWith('"') && value.endsWith('"'); - const isBoolean = value === "true" || value === "false"; - const isNumber = !isNaN(parseFloat(value)); - - return isString || isBoolean || isNumber; + const fnName = trimChar(value, ["(", ")"]).split(" ")[0].trim(); + const fnArgs = this.parseFunctionValueArgs(value); + + return { + identifier: fnName, + args: fnArgs, + }; + } + + /** + * Parses the value part of a line into a ParsedValue, which is + * composed out of piped parts separated by the forward slash `/` character. + * + * The ParsedValue will include the default value, if any, and a list of compute + * actions which will later be executed. + */ + private parsePipedValue(value: string): ParsedValue { + const parts = this.composePipedValueParts(value); + + if (this.isSimpleValue(parts[0])) { + return { + value: this.parseSimpleValue(parts[0]), + computeActions: parts.slice(1).map((p) => this.parseFunctionValue(p)), + }; } - /** - * Detects if the value is a function value. A function value is any - * of the following: - * - * - A function call with arguments: `(function-name *args)` - * - A function call by reference: `function-name` - * - * @param {string} value - * @returns {boolean} - */ - private isFunctionValue(value: string): boolean { - const isFnCall = value.startsWith("(") && value.endsWith(")"); - const isFnReference = !!value.match(/^([a-zA-Z0-9_-]+)$/); - - return isFnCall || isFnReference; + return { + value: null, + computeActions: parts.map((p) => this.parseFunctionValue(p)), + }; + } + + /** + * Takes the entire value part of a line and, assuming it is a function value, + * parses it into a list of arguments to be passed down to the function. + */ + private parseFunctionValueArgs(value: string): unknown[] { + const parts = value + .substring(1, value.length - 1) + .split(" ") + .slice(1); + + if (!parts.length) { + return []; } - /** - * Detects if the value is a piped value. A piped value is a mix of - * simple and function value parts, piped together with the forward - * slash `/` character. For example: - * - * ```yaml - * posts: (get-content "posts") / (limit 10) / only-published - * ``` - * - * or: - * - * ```yaml - * posts: "posts" / get-content / (limit 10) / only-published - * ``` - * - * The result of the previous pipe gets passed to the next as a first - * argument. - * - * @param {string} value - * @returns {boolean} - */ - private isPipedValue(value: string): boolean { - return this.composePipedValueParts(value).every(part => { - return this.isSimpleValue(part) || this.isFunctionValue(part) - }); - } + const normalizedParts = [parts[0]]; - /** - * Parses a value to a `ParsedValue` object, or `null` - * in case it could not for whatever reason. - * - * @param {string} value - * @returns {ParsedValue | null} - */ - private parseValue(value: string): ParsedValue | null { - if (this.isSimpleValue(value)) { - return { - value: this.parseSimpleValue(value), - computeActions: [], - }; - } - - if (this.isFunctionValue(value)) { - return { - value: null, - computeActions: [this.parseFunctionValue(value)], - }; - } - - if (this.isPipedValue(value)) { - return this.parsePipedValue(value); - } - - return null; - } + for (let i = 1; i < parts.length; i++) { + const untilCurrent = normalizedParts.join(" "); + const quoteCount = untilCurrent.split('"').length - 1; - /** - * Parses the value part of a line into a simple value, like for example - * a `string`, `number` or `boolean`. - * - * @param {string} value - * @returns {string | number | boolean} - */ - private parseSimpleValue(value: string): string | number | boolean { - if (value === "true" || value === "false") { - return value === "true"; - } - - if (!Number.isNaN(parseInt(value)) && value.indexOf('.') === -1) { - return parseInt(value); - } - - if (!Number.isNaN(parseFloat(value)) && value.indexOf('.') !== -1) { - return parseFloat(value); - } - - return trimChar(value, '"'); - } + if (quoteCount % 2 === 0) { + normalizedParts.push(parts[i]); + continue; + } - /** - * Parses the value part of a line into a Compute Action, which is - * later executed to run the function described in FlatMatter. - * - * @param {string} value - * @returns {ComputeAction} - */ - private parseFunctionValue(value: string): ComputeAction { - const isFn = value.startsWith("(") && value.endsWith(")"); - - if (!isFn) { - return { - identifier: value, - args: [], - }; - } - - const fnName = trimChar(value, ["(", ")"]).split(" ")[0].trim(); - const fnArgs = this.parseFunctionValueArgs(value); - - return { - identifier: fnName, - args: fnArgs, - }; - } + const lastIndex = normalizedParts.length - 1; + const lastPart = normalizedParts[lastIndex]; - /** - * Parses the value part of a line into a ParsedValue, which is - * composed out of piped parts separated by the forward slash `/` character. - * - * The ParsedValue will include the default value, if any, and a list of compute - * actions which will later be executed. - * - * @param {string} value - * @returns {ParsedValue} - */ - private parsePipedValue(value: string): ParsedValue { - const parts = this.composePipedValueParts(value); - - if (this.isSimpleValue(parts[0])) { - return { - value: this.parseSimpleValue(parts[0]), - computeActions: parts.slice(1).map((p) => this.parseFunctionValue(p)), - }; - } - - return { - value: null, - computeActions: parts.map((p) => this.parseFunctionValue(p)), - }; + normalizedParts[lastIndex] = `${lastPart} ${parts[i]}`; } - /** - * Takes the entire value part of a line and, assuming it is a function value, - * parses it into a list of arguments to be passed down to the function. - * - * @param {string} value - * @returns {unknown[]} - */ - private parseFunctionValueArgs(value: string): unknown[] { - const parts = value - .substring(1, value.length - 1) - .split(" ") - .slice(1); - - if (!parts.length) { - return []; - } - - const normalizedParts = [parts[0]]; - - for (let i = 1; i < parts.length; i++) { - const untilCurrent = normalizedParts.join(" "); - const quoteCount = untilCurrent.split('"').length - 1; - - if (quoteCount % 2 === 0) { - normalizedParts.push(parts[i]); - continue; - } - - const lastIndex = normalizedParts.length - 1; - const lastPart = normalizedParts[lastIndex]; - - normalizedParts[lastIndex] = `${lastPart} ${parts[i]}`; - } - - return normalizedParts.map((part) => this.parseSimpleValue(part)); - } + return normalizedParts.map((part) => this.parseSimpleValue(part)); + } + + /** + * Takes an entire value of a line and composes it into a list + * of piped parts. + */ + private composePipedValueParts(value: string): string[] { + const parts = value.split(" / "); + const normalizedParts = [parts[0]]; - /** - * Takes an entire value of a line and composes it into a list - * of piped parts. - * - * @param {string} value - * @returns {string[]} - */ - private composePipedValueParts(value: string): string[] { - const parts = value.split(" / "); - const normalizedParts = [parts[0]]; - - for (let i = 1; i < parts.length; i++) { - const untilCurrent = normalizedParts.join(" / "); - const quoteCount = untilCurrent.split('"').length - 1; - - if (quoteCount % 2 === 0) { - normalizedParts.push(parts[i]); - continue; - } - - const lastIndex = normalizedParts.length - 1; - const lastPart = normalizedParts[lastIndex]; - - normalizedParts[lastIndex] = `${lastPart} / ${parts[i]}`; - } - - return normalizedParts; + for (let i = 1; i < parts.length; i++) { + const untilCurrent = normalizedParts.join(" / "); + const quoteCount = untilCurrent.split('"').length - 1; + + if (quoteCount % 2 === 0) { + normalizedParts.push(parts[i]); + continue; + } + + const lastIndex = normalizedParts.length - 1; + const lastPart = normalizedParts[lastIndex]; + + normalizedParts[lastIndex] = `${lastPart} / ${parts[i]}`; } - /** - * Takes ParsedValue and, optionally an initial value, and runs - * compute actions over it to return the final computed value. - * - * @param {ParsedValue} parsedValue - * @returns {unknown} - */ - private computeValue(parsedValue: ParsedValue): unknown { - let value = parsedValue.value; + return normalizedParts; + } - for (const ca of parsedValue.computeActions) { - const fnInstance = this.functions.find((f) => f.name === ca.identifier); + /** + * Takes ParsedValue and, optionally an initial value, and runs + * compute actions over it to return the final computed value. + */ + private computeValue(parsedValue: ParsedValue): unknown { + let value = parsedValue.value; - if (!fnInstance) { - continue; - } + for (const ca of parsedValue.computeActions) { + const fnInstance = this.functions.find((f) => f.name === ca.identifier); - if (value !== null) { - ca.args = [value, ...ca.args]; - } + if (!fnInstance) { + continue; + } - value = fnInstance.compute(...ca.args); - } + if (value !== null) { + ca.args = [value, ...ca.args]; + } - return value; + value = fnInstance.compute(...ca.args); } - /** - * Takes a Serializer and uses it to transform internal data - * object to a desired output. - * - * @param {Serializer} serializer - * @returns {unknown} - */ - public serialize(serializer: Serializer): unknown { - return serializer.serialize(this.parsedConfig); - } + return value; + } + + /** + * Takes a Serializer and uses it to transform internal data + * object to a desired output. + */ + public serialize(serializer: Serializer): T { + return serializer.serialize(this.parsedConfig); + } } diff --git a/src/serializers/to_json.test.ts b/src/serializers/to_json.test.ts index 22f7ba8..4184ab1 100644 --- a/src/serializers/to_json.test.ts +++ b/src/serializers/to_json.test.ts @@ -2,11 +2,11 @@ import FlatMatter from "../flatmatter.ts"; import ToJson from "./to_json.ts"; test("Single-level configuration", () => { - const fm = new FlatMatter( - 'a: true\nb: false\nc: 1\nd: 12.5\nf: "some string"' - ); + const fm = new FlatMatter( + 'a: true\nb: false\nc: 1\nd: 12.5\nf: "some string"' + ); - const equal = "{\"a\":true,\"b\":false,\"c\":1,\"d\":12.5,\"f\":\"some string\"}"; - - expect(fm.serialize(new ToJson())).toStrictEqual(equal); + const equal = '{"a":true,"b":false,"c":1,"d":12.5,"f":"some string"}'; + + expect(fm.serialize(new ToJson())).toStrictEqual(equal); }); diff --git a/src/serializers/to_json.ts b/src/serializers/to_json.ts index 76148db..30cf417 100644 --- a/src/serializers/to_json.ts +++ b/src/serializers/to_json.ts @@ -1,7 +1,7 @@ import type { Serializer } from "../flatmatter.ts"; -export default class ToJson implements Serializer { - serialize(parsedConfig: Record): string { - return JSON.stringify(parsedConfig); +export default class ToJson implements Serializer { + serialize(config: Record): string { + return JSON.stringify(config); } } diff --git a/src/serializers/to_object.test.ts b/src/serializers/to_object.test.ts index 7059458..28cb78e 100644 --- a/src/serializers/to_object.test.ts +++ b/src/serializers/to_object.test.ts @@ -1,4 +1,4 @@ -import FlatMatter, {type FlatMatterFn} from "../flatmatter.ts"; +import FlatMatter, { type FlatMatterFn } from "../flatmatter.ts"; import ToObject from "./to_object.ts"; test("Single-level configuration", () => { @@ -48,7 +48,7 @@ test("Simple function usage", () => { } } - const fm = new FlatMatter('a: (to-upper "value")', [new ToUpper]); + const fm = new FlatMatter('a: (to-upper "value")', [new ToUpper()]); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ @@ -65,7 +65,7 @@ test("Piped function by reference usage", () => { } } - const fm = new FlatMatter('a: "value" / to-upper', [new ToUpper]); + const fm = new FlatMatter('a: "value" / to-upper', [new ToUpper()]); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ @@ -82,7 +82,7 @@ test("Piped function by call usage", () => { } } - const fm = new FlatMatter('a: "value" / (to-upper 123)', [new ToUpper]); + const fm = new FlatMatter('a: "value" / (to-upper 123)', [new ToUpper()]); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ @@ -95,16 +95,16 @@ test("Invalid value in pipe", () => { const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({}); -}) +}); test("Invalid value in pipe, 2", () => { const fm = new FlatMatter('a: "value" / asd'); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ - a: "value" + a: "value", }); -}) +}); test("Only piped functions", () => { class FirstFn implements FlatMatterFn { @@ -123,11 +123,14 @@ test("Only piped functions", () => { } } - const fm = new FlatMatter('a: (first-fn "value / here") / second-fn', [new FirstFn, new SecondFn]); + const fm = new FlatMatter('a: (first-fn "value / here") / second-fn', [ + new FirstFn(), + new SecondFn(), + ]); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ - a: "VALUE / HERE-passed-by-second" + a: "VALUE / HERE-passed-by-second", }); }); @@ -140,13 +143,13 @@ test("Function call without any args", () => { } } - const fm = new FlatMatter('a: "value" / (to-upper)', [new ToUpper]); + const fm = new FlatMatter('a: "value" / (to-upper)', [new ToUpper()]); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ a: "VALUE", }); -}) +}); test("Function call using multiple strings with spaces as arg", () => { class ToUpper implements FlatMatterFn { @@ -157,10 +160,12 @@ test("Function call using multiple strings with spaces as arg", () => { } } - const fm = new FlatMatter('a: (to-upper "value goes here" "and here")', [new ToUpper]); + const fm = new FlatMatter('a: (to-upper "value goes here" "and here")', [ + new ToUpper(), + ]); const config = fm.serialize(new ToObject()); expect(config).toStrictEqual({ a: "VALUE GOES HERE", }); -}) \ No newline at end of file +}); diff --git a/src/serializers/to_object.ts b/src/serializers/to_object.ts index a7161cc..79b2886 100644 --- a/src/serializers/to_object.ts +++ b/src/serializers/to_object.ts @@ -1,7 +1,7 @@ -import type {Serializer} from "../flatmatter.ts"; +import type { Serializer } from "../flatmatter.ts"; -export default class ToObject implements Serializer { - serialize(parsedConfig: Record): Record { - return parsedConfig; +export default class ToObject implements Serializer> { + serialize(config: Record): Record { + return config; } } diff --git a/src/utils.ts b/src/utils.ts index 56995fc..b334380 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,9 +1,5 @@ /** * Trims char(s) from both sides of the given input string. - - * @param {string} input - * @param {string | string[]} char - * @returns {string} */ export function trimChar(input: string, char: string | string[]): string { if (typeof char === "string") { -- cgit v1.2.3