Skip to content

Commit

Permalink
fix: Load Mermaid only when the Mermaid Block is visible (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
ericof committed Feb 24, 2024
1 parent f6aed35 commit 3ef3a01
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 64 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
context('Blocks Acceptance Tests', () => {
describe('Text Block Tests', () => {
context('Code Block Acceptance Tests', () => {
describe('Code Block Tests', () => {
beforeEach(() => {
// given a logged in editor and a page in edit mode
cy.visit('/');
Expand Down
39 changes: 39 additions & 0 deletions acceptance/cypress/tests/block_mermaid.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
context('Mermaid Block Acceptance Tests', () => {
describe('Mermaid Block Tests', () => {
beforeEach(() => {
// given a logged in editor and a page in edit mode
cy.visit('/');
cy.autologin();
cy.createContent({
contentType: 'Document',
contentId: 'document',
contentTitle: 'Test document',
});
cy.createContent({
contentType: 'Document',
contentId: 'my-page',
contentTitle: 'My Page',
path: '/document',
});
cy.visit('/document');
cy.navigate('/document/edit');
});

it('As editor I can add a Mermaid Block', function () {
cy.intercept('PATCH', '/**/document').as('edit');
cy.intercept('GET', '/**/document').as('content');
cy.intercept('GET', '/**/Document').as('schema');

cy.getSlate().click();
cy.get('.button .block-add-button').click({ force: true });
cy.get('.blocks-chooser .text .button.mermaidBlock').click({ force: true });
cy.get('pre.language-mermaid + textarea')
.click()
.type('sequenceDiagram\n Alice->>John: Hello John, how are you?\nJohn-->>Alice: Great!\nAlice-)John: See you later!');
cy.get('#toolbar-save').click();
cy.wait(100);
cy.get('.mermaidWrapper > div > svg')
.should('be.visible')
});
});
});
10 changes: 8 additions & 2 deletions dockerfiles/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,18 @@ services:
args:
ADDON_NAME: "${ADDON_NAME}"
ADDON_PATH: "${ADDON_PATH}"
VOLTO_VERSION: ${VOLTO_VERSION:-17}
VOLTO_VERSION: "${VOLTO_VERSION:-17}"
volumes:
- ${CURRENT_DIR}:/app/src/addons/${ADDON_PATH}/
environment:
RAZZLE_INTERNAL_API_PATH: http://backend:8080/Plone
RAZZLE_API_PATH: http://localhost:8080/Plone
# In case that you want to connect to and outside (non-docker) local instance
# coment the above, use the next line
# RAZZLE_INTERNAL_API_PATH: http://host.docker.internal:8080/Plone
RAZZLE_API_PATH: http://127.0.0.1:8080/Plone
HOST: 0.0.0.0
depends_on:
- backend
ports:
- 3000:3000
- 3001:3001
Expand Down
22 changes: 4 additions & 18 deletions dockerfiles/storybook.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,7 @@ const defaultRazzleOptions = {
staticCssInDev: false,
emitOnErrors: false,
disableWebpackbar: false,
browserslist: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie 11',
'not dead',
],
browserslist: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie 11', 'not dead'],
};

module.exports = {
Expand Down Expand Up @@ -116,9 +110,7 @@ module.exports = {
// Put the SVG loader on top and prevent the asset/resource rule
// from processing the app's SVGs
config.module.rules.unshift(SVGLOADER);
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test.test('.svg'),
);
const fileLoaderRule = config.module.rules.find((rule) => rule.test.test('.svg'));
fileLoaderRule.exclude = /icons\/.*\.svg$/;

config.plugins.unshift(
Expand All @@ -139,9 +131,7 @@ module.exports = {
};

// Addons have to be loaded with babel
const addonPaths = registry.addonNames.map((addon) =>
fs.realpathSync(registry.packages[addon].modulePath),
);
const addonPaths = registry.addonNames.map((addon) => fs.realpathSync(registry.packages[addon].modulePath));
resultConfig.module.rules[1].exclude = (input) =>
// exclude every input from node_modules except from @plone/volto
/node_modules\/(?!(@plone\/volto)\/)/.test(input) &&
Expand All @@ -150,11 +140,7 @@ module.exports = {

const addonExtenders = registry.getAddonExtenders().map((m) => require(m));

const extendedConfig = addonExtenders.reduce(
(acc, extender) =>
extender.modify(acc, { target: 'web', dev: 'dev' }, config),
resultConfig,
);
const extendedConfig = addonExtenders.reduce((acc, extender) => extender.modify(acc, { target: 'web', dev: 'dev' }, config), resultConfig);

// Note: we don't actually support razzle plugins, which are also a feature
// of the razzle.extend.js addons file. Those features are probably
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"@plone/volto": ">=17.0.0"
},
"dependencies": {
"prismjs": "1.29.0"
"prismjs": "1.29.0",
"mermaid": "10.8.0"
},
"devDependencies": {
"@plone/scripts": "^3.0.0",
Expand Down
37 changes: 27 additions & 10 deletions src/components/Blocks/Mermaid/DefaultView.jsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
import React, { useEffect, useState } from 'react';

const MermaidView = (props) => {
const { code } = props;
const [loaded, setLoaded] = useState(false);
const { code, block } = props;
const elementId = `mermaid-${block}`;
const [mermaid, setMermaid] = useState(null);
const [svg, setSVG] = useState('');

useEffect(() => {
if (window.mermaid) {
setLoaded(true);
}
}, [loaded]);
const loadMermaid = async () => {
const config = { startOnLoad: true, flowchart: { useMaxWidth: false, htmlLabels: true } };
const { default: mermaid } = await import('mermaid/dist/mermaid.esm.mjs');
setMermaid(mermaid);
mermaid.initialize(config);
};

loadMermaid();
return () => {};
}, []);

useEffect(() => {
if (loaded && window.mermaid) {
window.mermaid.contentLoaded();
if (__CLIENT__ && mermaid && elementId && code) {
const renderSVG = async () => {
const { svg } = await mermaid.render(elementId, code);
setSVG(svg);
};

renderSVG();
return () => {};
}
}, [loaded, code]);
return <>{code && <pre className="mermaid">{code}</pre>}</>;
}, [mermaid, elementId, code]);

return <div className={'mermaidWrapper'}>{svg && <div dangerouslySetInnerHTML={{ __html: svg }} />}</div>;
};

export default MermaidView;
4 changes: 2 additions & 2 deletions src/components/Blocks/Mermaid/View.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import MermaidView from './DefaultView';
import { withBlockExtensions } from '@plone/volto/helpers';

const MermaidBlockView = (props) => {
const { data } = props;
const { block, data } = props;
const code = data.code || '';
return <>{code && <MermaidView code={code} />}</>;
return <>{code && <MermaidView code={code} block={block} />}</>;
};

export default withBlockExtensions(MermaidBlockView);
19 changes: 0 additions & 19 deletions src/helpers/Mermaid/MermaidConfig.jsx

This file was deleted.

10 changes: 0 additions & 10 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import codeSVG from '@plone/volto/icons/code.svg';
import showcaseSVG from '@plone/volto/icons/showcase.svg';

import MermaidConfig from './helpers/Mermaid/MermaidConfig';

import CodeBlockViewBlock from './components/Blocks/Code/View';
import CodeBlockEditBlock from './components/Blocks/Code/Edit';

Expand Down Expand Up @@ -31,14 +29,6 @@ import 'prismjs/components/prism-yaml';
import { languages } from 'prismjs/components/prism-core';

const applyConfig = (config) => {
config.settings.appExtras = [
...config.settings.appExtras,
{
match: '',
component: MermaidConfig,
},
];

config.blocks.blocksConfig.codeBlock = {
id: 'codeBlock',
title: 'Code Block',
Expand Down

0 comments on commit 3ef3a01

Please sign in to comment.