diff --git a/src/helpers/nodeMatchers.ts b/src/helpers/nodeMatchers.ts index 48ae242d..2dff79f8 100644 --- a/src/helpers/nodeMatchers.ts +++ b/src/helpers/nodeMatchers.ts @@ -19,10 +19,10 @@ const rootClassRegex = classRegex("h"); const propClassRegex = classRegex("(p|e|u|dt)"); export const isParentNode = (node: MixedNode): node is ParentNode => - Boolean(node.hasOwnProperty("tagName") && node.hasOwnProperty("childNodes")); + "tagName" in node && "childNodes" in node; export const isTextNode = (node: MixedNode): node is DefaultTreeTextNode => - Boolean(node.hasOwnProperty("value")); + "value" in node; export const isMicroformatV2Root = (node: ParentNode): boolean => getClassNames(node).some((cl) => cl.match(rootClassRegex)); diff --git a/src/validator.ts b/src/validator.ts index 856e92a5..9662a9ed 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -1,70 +1,72 @@ import { ParentNode } from "./types"; import { isParentNode } from "./helpers/nodeMatchers"; -export const validator = (html: unknown, options: unknown): void => { - if (typeof html === "undefined") { - throw new TypeError("Microformats parser: HTML not provided"); +const assertIsString = (str: unknown, name: string): string => { + if (typeof str === "undefined") { + throw new TypeError(`Microformats parser: ${name} not provided`); } - if (typeof html !== "string") { - throw new TypeError("Microformats parser: HTML is not a string"); + if (typeof str !== "string") { + throw new TypeError(`Microformats parser: ${name} is not a string`); } - if (html === "") { - throw new TypeError("Microformats parser: HTML cannot be empty"); + if (str === "") { + throw new TypeError(`Microformats parser: ${name} cannot be empty`); } - if (typeof options === "undefined") { - throw new TypeError("Microformats parser: options is not provided"); - } + return str; +}; - if (typeof options !== "object") { - throw new TypeError("Microformats parser: options is not an object"); +const assertIsBoolean = (bool: unknown, name: string): boolean => { + if (typeof bool !== "boolean") { + throw new TypeError(`Microformats parser: ${name} is not a boolean`); } - if (options === null) { - throw new TypeError("Microformats parser: options cannot be null"); - } + return bool; +}; - // eslint-disable-next-line - //@ts-ignore - const { baseUrl } = options; +const assertIsObject = ( + obj: unknown, + name: string +): Record => { + if (typeof obj === "undefined") { + throw new TypeError(`Microformats parser: ${name} is not provided`); + } - if (typeof baseUrl === "undefined") { - throw new TypeError("Microformats parser: baseUrl not provided"); + if (typeof obj !== "object") { + throw new TypeError(`Microformats parser: ${name} is not an object`); } - if (typeof baseUrl !== "string") { - throw new TypeError("Microformats parser: baseUrl is not a string"); + if (Array.isArray(obj)) { + throw new TypeError(`Microformats parser: ${name} is not an object`); } - if (baseUrl === "") { - throw new TypeError("Microformats parser: baseUrl cannot be empty"); + if (obj === null) { + throw new TypeError(`Microformats parser: ${name} cannot be null`); } - // verify the url provided is valid - new URL(baseUrl); + return obj as Record; +}; - // eslint-disable-next-line - //@ts-ignore - const { experimental } = options; +export const validator = ( + unknownHtml: unknown, + unknownOptions: unknown +): void => { + assertIsString(unknownHtml, "HTML"); - if (typeof experimental !== "undefined" && typeof experimental !== "object") { - throw new TypeError("Microformats parser: experimental is not an object"); - } + const options = assertIsObject(unknownOptions, "options"); - if (typeof experimental === "object" && Array.isArray(experimental)) { - throw new TypeError("Microformats parser: experimental is not an object"); - } + const baseUrl = assertIsString(options.baseUrl, "baseUrl"); + + // verify the url provided is valid + new URL(baseUrl); + + if ("experimental" in options) { + const experimental = assertIsObject(options.experimental, "experimental"); - if ( - experimental && - "lang" in experimental && - typeof experimental.lang !== "boolean" - ) { - throw new TypeError( - "Microformats parser: experimental.lang is not a boolean" - ); + if ("lang" in experimental) { + assertIsBoolean(experimental.lang, "experimental.lang"); + } } }; diff --git a/test/validation.spec.ts b/test/validation.spec.ts index 8c1f64d2..6483dcdd 100644 --- a/test/validation.spec.ts +++ b/test/validation.spec.ts @@ -108,6 +108,12 @@ describe("validation", () => { }); describe("experimental", () => { + it("should not throw an error if it is an empty object", () => { + expect(() => + mf2(html, { baseUrl: "http://example.com", experimental: {} }) + ).to.not.throw(); + }); + it("should throw an error if it is not an object", () => { expect(() => mf2(html, { baseUrl: "http://example.com", experimental: "" })