From b0bf6deb658f6a47a60a405362c3351870d2bc57 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 1 Dec 2021 20:22:52 -0500 Subject: [PATCH 1/6] Set up spys instead of using mock jest.mock doesn't work work against ES6 modules, but this approach of using spys instead does. See: https://github.com/facebook/jest/issues/10025 --- src/Mermaid.spec.tsx | 57 +++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/src/Mermaid.spec.tsx b/src/Mermaid.spec.tsx index ca0e8fb..3e1a7d8 100644 --- a/src/Mermaid.spec.tsx +++ b/src/Mermaid.spec.tsx @@ -11,9 +11,16 @@ import React from 'react' import renderer from 'react-test-renderer' import mermaid from 'mermaid' + +import { jest } from '@jest/globals' + +const spy = { + initialize: jest.spyOn(mermaid, 'initialize').mockImplementation(() => {}), + contentLoaded: jest.spyOn(mermaid, 'contentLoaded').mockImplementation(() => {}) +} + import { Mermaid } from './Mermaid' -jest.mock('mermaid') afterEach(() => { jest.clearAllMocks() @@ -22,14 +29,14 @@ afterEach(() => { it('renders without diagram', () => { const component = renderer.create() expect(component.toJSON()).toMatchSnapshot() - expect(mermaid.initialize).toBeCalledTimes(0) - expect(mermaid.contentLoaded).toBeCalledTimes(0) + expect(spy.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toHaveBeenCalled() - expect(mermaid.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toHaveBeenCalled() + expect(spy.initialize).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toBeCalledTimes(1) - expect(mermaid.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(1) + expect(spy.initialize).toBeCalledTimes(0) }) it('renders with diagram', () => { @@ -39,14 +46,14 @@ it('renders with diagram', () => { B-->D; C-->D;`} />) expect(component.toJSON()).toMatchSnapshot() - expect(mermaid.initialize).toBeCalledTimes(0) - expect(mermaid.contentLoaded).toBeCalledTimes(0) + expect(spy.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toHaveBeenCalled() - expect(mermaid.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toHaveBeenCalled() + expect(spy.initialize).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toBeCalledTimes(1) - expect(mermaid.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(1) + expect(spy.initialize).toBeCalledTimes(0) }) it('renders with config', () => { @@ -56,14 +63,14 @@ it('renders with config', () => { B-->D; C-->D;`} config={{}} />) expect(component.toJSON()).toMatchSnapshot() - expect(mermaid.initialize).toBeCalledTimes(0) - expect(mermaid.contentLoaded).toBeCalledTimes(0) + expect(spy.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toHaveBeenCalled() - expect(mermaid.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toHaveBeenCalled() + expect(spy.initialize).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toBeCalledTimes(1) - expect(mermaid.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(1) + expect(spy.initialize).toBeCalledTimes(0) }) it('renders with mermaid config', () => { @@ -73,12 +80,12 @@ it('renders with mermaid config', () => { B-->D; C-->D;`} config={{ mermaid: { theme: 'dark' } } } />) expect(component.toJSON()).toMatchSnapshot() - expect(mermaid.initialize).toBeCalledTimes(0) - expect(mermaid.contentLoaded).toBeCalledTimes(0) + expect(spy.initialize).toBeCalledTimes(0) + expect(spy.contentLoaded).toBeCalledTimes(0) component.update() - expect(mermaid.contentLoaded).toHaveBeenCalled() - expect(mermaid.initialize).toHaveBeenNthCalledWith(1, { startOnLoad: true, theme: 'dark' }) + expect(spy.contentLoaded).toHaveBeenCalled() + expect(spy.initialize).toHaveBeenNthCalledWith(1, { startOnLoad: true, theme: 'dark' }) component.update() - expect(mermaid.contentLoaded).toBeCalledTimes(1) - expect(mermaid.initialize).toBeCalledTimes(1) + expect(spy.contentLoaded).toBeCalledTimes(1) + expect(spy.initialize).toBeCalledTimes(1) }) From 1381f13859c5bff65cdd3a598109a320d4d50e02 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 1 Dec 2021 20:34:32 -0500 Subject: [PATCH 2/6] Export as an ES6 module instead of CommonJS --- jest.config.js | 10 ++++++++-- package.json | 3 ++- src/mdxast-mermaid.ts | 4 +--- tsconfig.json | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/jest.config.js b/jest.config.js index 6d137bd..a56900e 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,12 @@ /** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */ -module.exports = { - preset: 'ts-jest', +export default { + preset: 'ts-jest/presets/default-esm', + transform: {}, + globals: { + 'ts-jest': { + useESM: true + } + }, testEnvironment: 'node', coverageThreshold: { global: { diff --git a/package.json b/package.json index bf39a32..1fc6f0a 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,10 @@ }, "author": "Sam Wall (oss@samuelwall.co.uk)", "license": "MIT", + "type": "module", "scripts": { "build": "rimraf lib && tsc", - "test": "jest --coverage" + "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js --coverage" }, "repository": { "type": "git", diff --git a/src/mdxast-mermaid.ts b/src/mdxast-mermaid.ts index a8eabc7..d8e2cd6 100644 --- a/src/mdxast-mermaid.ts +++ b/src/mdxast-mermaid.ts @@ -21,7 +21,7 @@ type CodeMermaid = Literal & { * @param config Config passed in from parser. * @returns Function to transform mdxast. */ -function plugin (config?: Config) { + export default function plugin (config?: Config) { /** * Insert the component import into the document. * @param ast The document to insert into. @@ -92,5 +92,3 @@ function plugin (config?: Config) { return ast } } - -export = plugin diff --git a/tsconfig.json b/tsconfig.json index b5aa56a..e7f7876 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,17 +1,18 @@ { "compilerOptions": { "declaration": true, + "allowSyntheticDefaultImports": true, "esModuleInterop": true, "jsx": "react", "lib": ["ESNext", "DOM"], - "module": "CommonJS", + "module": "ESNext", "moduleResolution": "node", "noImplicitAny": false, "outDir": "lib", "rootDir": "src", "sourceMap": true, "strict": true, - "target": "ES2015" + "target": "ESNext" }, "include": [ "src/**/*.ts", From aea7fb935859aafd3ca614551c59443425640ea2 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 1 Dec 2021 20:48:07 -0500 Subject: [PATCH 3/6] Upgrade unist-util-visit to 3.0.0 --- package.json | 4 ++-- src/mdxast-mermaid.ts | 10 +++++----- yarn.lock | 22 ++++++++++++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1fc6f0a..df5558e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "peerDependencies": { "mermaid": "^8.0.0", "react": "^16.8.4 || ^17.0.0", - "unist-util-visit": "^2.0.0" + "unist-util-visit": "^3.0.0" }, "devDependencies": { "@mdx-js/mdx": "^1.6.22", @@ -58,6 +58,6 @@ "rimraf": "^3.0.2", "ts-jest": "^27.0.4", "typescript": "^4.3.5", - "unist-util-visit": "^2.0.0" + "unist-util-visit": "^3.0.0" } } diff --git a/src/mdxast-mermaid.ts b/src/mdxast-mermaid.ts index d8e2cd6..e8fafd8 100644 --- a/src/mdxast-mermaid.ts +++ b/src/mdxast-mermaid.ts @@ -5,7 +5,7 @@ * license file in the root directory of this source tree. */ -import visit from 'unist-util-visit' +import { visit, EXIT } from 'unist-util-visit' import { Literal, Parent, Node, Data } from 'unist' import { Config } from './config.model' @@ -21,7 +21,7 @@ type CodeMermaid = Literal & { * @param config Config passed in from parser. * @returns Function to transform mdxast. */ - export default function plugin (config?: Config) { +export default function plugin (config?: Config) { /** * Insert the component import into the document. * @param ast The document to insert into. @@ -32,7 +32,7 @@ type CodeMermaid = Literal & { visit(ast, { type: 'import' }, (node: Literal) => { if (/\s*import\s*{\s*Mermaid\s*}\s*from\s*'mdx-mermaid(\/lib)?\/Mermaid'\s*;?\s*/.test(node.value)) { importFound = true - return visit.EXIT + return EXIT } }) @@ -49,7 +49,7 @@ type CodeMermaid = Literal & { // Find all the mermaid diagram code blocks. i.e. ```mermaid const instances: [Literal, number, Parent | Literal, Data>][] = [] visit(ast, { type: 'code', lang: 'mermaid' }, (node, index, parent) => { - instances.push([node, index, parent as Parent, Data>]) + instances.push([node, index!, parent as Parent, Data>]) }) // If there are no code blocks return if (!instances.length) { @@ -64,7 +64,7 @@ type CodeMermaid = Literal & { node.value.substring(index) } insertImport(ast) - return visit.EXIT + return EXIT } }) return ast diff --git a/yarn.lock b/yarn.lock index af0baa2..015579d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5931,6 +5931,11 @@ unist-util-is@^4.0.0: resolved "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz" integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== +unist-util-is@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" + integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== + unist-util-position@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.1.0.tgz#1c42ee6301f8d52f47d14f62bbdb796571fa2d47" @@ -5965,6 +5970,14 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" +unist-util-visit-parents@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2" + integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit@2.0.3, unist-util-visit@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz" @@ -5974,6 +5987,15 @@ unist-util-visit@2.0.3, unist-util-visit@^2.0.0: unist-util-is "^4.0.0" unist-util-visit-parents "^3.0.0" +unist-util-visit@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b" + integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^4.0.0" + universalify@^0.1.0, universalify@^0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz" From 55bf72233fbae911b6fa3f24c54cbc5a55d2c790 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Wed, 1 Dec 2021 21:43:45 -0500 Subject: [PATCH 4/6] Upgrade unist-util-visit to 4.1.0 Closes: https://github.com/sjwall/mdx-mermaid/issues/18 --- package.json | 4 ++-- src/mdxast-mermaid.ts | 8 ++++---- yarn.lock | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index df5558e..e675018 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "peerDependencies": { "mermaid": "^8.0.0", "react": "^16.8.4 || ^17.0.0", - "unist-util-visit": "^3.0.0" + "unist-util-visit": "^4.1.0" }, "devDependencies": { "@mdx-js/mdx": "^1.6.22", @@ -58,6 +58,6 @@ "rimraf": "^3.0.2", "ts-jest": "^27.0.4", "typescript": "^4.3.5", - "unist-util-visit": "^3.0.0" + "unist-util-visit": "^4.1.0" } } diff --git a/src/mdxast-mermaid.ts b/src/mdxast-mermaid.ts index e8fafd8..ab5bc06 100644 --- a/src/mdxast-mermaid.ts +++ b/src/mdxast-mermaid.ts @@ -26,7 +26,7 @@ export default function plugin (config?: Config) { * Insert the component import into the document. * @param ast The document to insert into. */ - function insertImport (ast: Parent | Literal, Data>) { + function insertImport (ast: any) { // See if there is already an import for the Mermaid component let importFound = false visit(ast, { type: 'import' }, (node: Literal) => { @@ -45,16 +45,16 @@ export default function plugin (config?: Config) { } } - return async function transformer (ast: Parent | Literal, Data>): Promise { + return async function transformer (ast: any): Promise { // Find all the mermaid diagram code blocks. i.e. ```mermaid const instances: [Literal, number, Parent | Literal, Data>][] = [] - visit(ast, { type: 'code', lang: 'mermaid' }, (node, index, parent) => { + visit(ast, { type: 'code', lang: 'mermaid' }, (node: CodeMermaid, index, parent) => { instances.push([node, index!, parent as Parent, Data>]) }) // If there are no code blocks return if (!instances.length) { // Look for any components - visit & { type: 'jsx' }>(ast, { type: 'jsx' }, (node, index, parent) => { + visit(ast, { type: 'jsx' }, (node: Literal & { type: 'jsx' }, index, parent) => { if (/.* Date: Mon, 13 Dec 2021 16:44:44 -0500 Subject: [PATCH 5/6] Use `import` instead of `require` --- doc/docusaurus.config.js | 2 +- readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/docusaurus.config.js b/doc/docusaurus.config.js index 9f6ea4d..d75f000 100644 --- a/doc/docusaurus.config.js +++ b/doc/docusaurus.config.js @@ -83,7 +83,7 @@ const config = { /** @type {import('@docusaurus/preset-classic').Options} */ ({ docs: { - remarkPlugins: [require('mdx-mermaid')], + remarkPlugins: [import('mdx-mermaid')], sidebarPath: require.resolve('./sidebars.js'), // Please change this to your repo. editUrl: diff --git a/readme.md b/readme.md index cc977c8..fb5c6f5 100644 --- a/readme.md +++ b/readme.md @@ -31,7 +31,7 @@ Update `docusaurus.config.js` '@docusaurus/preset-classic', { docs: { - remarkPlugins: [require('mdx-mermaid')], + remarkPlugins: [import('mdx-mermaid')], ``` Use code blocks in `.md` or `.mdx` files: From ad07917b75e32f2e9fa03c0a2b02ffddd31db5a5 Mon Sep 17 00:00:00 2001 From: Craig Andrews Date: Sat, 18 Dec 2021 12:25:45 -0500 Subject: [PATCH 6/6] Use ES2020 instead of ESNext It's best to use a specific version to ensure a consistent, reproducible product. --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index e7f7876..edec168 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,14 +5,14 @@ "esModuleInterop": true, "jsx": "react", "lib": ["ESNext", "DOM"], - "module": "ESNext", + "module": "ES2020", "moduleResolution": "node", "noImplicitAny": false, "outDir": "lib", "rootDir": "src", "sourceMap": true, "strict": true, - "target": "ESNext" + "target": "ES2020" }, "include": [ "src/**/*.ts",