Skip to content

Commit

Permalink
feat: Add Gist Block and Caption component
Browse files Browse the repository at this point in the history
  • Loading branch information
ericof committed Feb 25, 2024
1 parent 68d4505 commit e0d368e
Show file tree
Hide file tree
Showing 12 changed files with 291 additions and 11 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
},
"dependencies": {
"prismjs": "1.29.0",
"mermaid": "10.8.0"
"mermaid": "10.8.0",
"react-gist": "1.2.4"
},
"devDependencies": {
"@plone/scripts": "^3.0.0",
Expand Down
3 changes: 3 additions & 0 deletions src/components/Blocks/Code/DefaultView.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import SyntaxHighlighter from '../../SyntaxHighlighter/SyntaxHighlighter';
import Caption from '../../Caption/Caption';

const CodeView = (props) => {
const { data } = props;
const { code, style, language, lineNbr, showLineNumbers, wrapLongLines } = data;
const { caption_title, caption_description } = data;
const styleWrap = wrapLongLines ? 'wrapLongLines' : '';
const className = `code-block-wrapper ${style} ${styleWrap}`;

Expand All @@ -16,6 +18,7 @@ const CodeView = (props) => {
</div>
</div>
)}
{caption_title && <Caption title={caption_title} description={caption_description} />}
</>
);
};
Expand Down
4 changes: 3 additions & 1 deletion src/components/Blocks/Code/Edit.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { withBlockExtensions } from '@plone/volto/helpers';
import { SidebarPortal } from '@plone/volto/components';
import config from '@plone/volto/registry';
import CodeBlockData from './Data';
import Caption from '../../Caption/Caption.jsx';
import Editor from '../../Editor/Editor.tsx';
import { highlight } from 'prismjs/components/prism-core';

Expand All @@ -19,7 +20,7 @@ const CodeBlockEdit = (props) => {
}
const allLanguages = config.settings.codeBlock.languages;
const language = allLanguages[data.language].language;

const { caption_title, caption_description } = data;
const handleChange = (code) => {
setCode(code);
onChangeBlock(block, { ...data, code: code });
Expand All @@ -29,6 +30,7 @@ const CodeBlockEdit = (props) => {
<div className="block code">
<div className={className}>
<Editor value={code} onValueChange={(code) => handleChange(code)} highlight={(code) => highlight(code, language)} padding={10} preClassName={`code-block-wrapper ${data.style} language-${data.language}`} />
{caption_title && <Caption title={caption_title} description={caption_description} />}
<SidebarPortal selected={selected}>
<CodeBlockData {...props} />
</SidebarPortal>
Expand Down
20 changes: 20 additions & 0 deletions src/components/Blocks/Code/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ const messages = defineMessages({
id: 'Starting Line Number',
defaultMessage: 'Starting Line Number',
},
caption_title: {
id: 'Title',
defaultMessage: 'Title',
},
caption_description: {
id: 'Description',
defaultMessage: 'Description',
},
});

export const codeSchema = (props) => {
Expand All @@ -53,6 +61,11 @@ export const codeSchema = (props) => {
title: 'Default',
fields: ['language', 'style', 'showLineNumbers', 'wrapLongLines', 'lineNbr'],
},
{
id: 'caption',
title: 'Caption',
fields: ['caption_title', 'caption_description'],
},
],

properties: {
Expand Down Expand Up @@ -83,6 +96,13 @@ export const codeSchema = (props) => {
type: 'integer',
default: 1,
},
caption_title: {
title: props.intl.formatMessage(messages.caption_title),
},
caption_description: {
title: props.intl.formatMessage(messages.caption_description),
widget: 'textarea',
},
},
required: ['language'],
};
Expand Down
27 changes: 27 additions & 0 deletions src/components/Blocks/Gist/Data.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import { BlockDataForm } from '@plone/volto/components';
import { gistSchema } from './schema';
import { useIntl } from 'react-intl';

const GistBlockData = (props) => {
const { data, block, onChangeBlock } = props;
const intl = useIntl();
const schema = gistSchema({ ...props, intl });

return (
<BlockDataForm
schema={schema}
title={schema.title}
onChangeField={(id, value) => {
onChangeBlock(block, {
...data,
[id]: value,
});
}}
formData={data}
block={block}
/>
);
};

export default GistBlockData;
15 changes: 15 additions & 0 deletions src/components/Blocks/Gist/DefaultView.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import Gist from 'react-gist';
import Caption from '../../Caption/Caption';

const GistView = (props) => {
const { file, gistId, caption_title, caption_description } = props;
return (
<>
{gistId && <Gist id={gistId} file={file} />}
{caption_title && <Caption title={caption_title} description={caption_description} />}
</>
);
};

export default GistView;
26 changes: 26 additions & 0 deletions src/components/Blocks/Gist/Edit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { withBlockExtensions } from '@plone/volto/helpers';
import { SidebarPortal } from '@plone/volto/components';
import GistBlockData from './Data';
import View from './DefaultView';

const GistBlockEdit = (props) => {
const { data, selected, block } = props;
const { gistId, file } = data;
const { caption_title, caption_description } = data;
return (
<div className="block gist edit" id={`gistBlock-${block}`}>
{data && (
<>
<div className={'gist editLayer'}></div>
<View gistId={gistId} file={file} caption_title={caption_title} caption_description={caption_description} />
</>
)}
<SidebarPortal selected={selected}>
<GistBlockData {...props} />
</SidebarPortal>
</div>
);
};

export default withBlockExtensions(GistBlockEdit);
15 changes: 15 additions & 0 deletions src/components/Blocks/Gist/View.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { withBlockExtensions } from '@plone/volto/helpers';
import GistView from './DefaultView';

const GistBlockView = (props) => {
const { data, block } = props;
const { gistId, file, caption_title, caption_description } = data;
return (
<div className="block gist view" id={`gistBlock-${block}`}>
{data && <GistView caption_title={caption_title} caption_description={caption_description} gistId={gistId} file={file} block={block} />}
</div>
);
};

export default withBlockExtensions(GistBlockView);
59 changes: 59 additions & 0 deletions src/components/Blocks/Gist/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { defineMessages } from 'react-intl';

const messages = defineMessages({
gistBlock: {
id: 'Gist Block',
defaultMessage: 'Gist Block',
},
gistId: {
id: 'Gist Id',
defaultMessage: 'Gist Id',
},
file: {
id: 'File',
defaultMessage: 'File',
},
caption_title: {
id: 'Title',
defaultMessage: 'Title',
},
caption_description: {
id: 'Description',
defaultMessage: 'Description',
},
});

export const gistSchema = (props) => {
return {
title: props.intl.formatMessage(messages.gistBlock),
fieldsets: [
{
id: 'default',
title: 'Default',
fields: ['gistId', 'file'],
},
{
id: 'caption',
title: 'Caption',
fields: ['caption_title', 'caption_description'],
},
],

properties: {
gistId: {
title: props.intl.formatMessage(messages.gistId),
},
file: {
title: props.intl.formatMessage(messages.file),
},
caption_title: {
title: props.intl.formatMessage(messages.caption_title),
},
caption_description: {
title: props.intl.formatMessage(messages.caption_description),
widget: 'textarea',
},
},
required: ['gistId'],
};
};
39 changes: 39 additions & 0 deletions src/components/Caption/Caption.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* @module components/Caption
*/
import React from 'react';
import PropTypes from 'prop-types';

/**
* Image/video caption component class.
* @function Caption
* @params {string} title Caption title.
* @params {string} description Caption description.
* @returns {string} Markup of the component.
*/
const Caption = ({ title, description }) => {
return (
<div className={'codeBlockCaption'}>
{title && <p className="title">{title}</p>}
{description && (
<p className="description">
{description.split('\n').map((line, index) => (
<p key={index}>{line || '\u00A0'}</p>
))}
</p>
)}
</div>
);
};

/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
Caption.propTypes = {
title: PropTypes.string,
description: PropTypes.string,
};

export default Caption;
45 changes: 36 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import codeSVG from '@plone/volto/icons/code.svg';
import showcaseSVG from '@plone/volto/icons/showcase.svg';

import CodeBlockViewBlock from './components/Blocks/Code/View';
import CodeBlockEditBlock from './components/Blocks/Code/Edit';
// Blocks - CodeBlock
import CodeBlockView from './components/Blocks/Code/View';
import CodeBlockEdit from './components/Blocks/Code/Edit';

// Blocks - MermaidBlock
import MermaidBlockEdit from './components/Blocks/Mermaid/Edit';
import MermaidBlockView from './components/Blocks/Mermaid/View';

// Blocks - GistBlock
import GistBlockEdit from './components/Blocks/Gist/Edit';
import GistBlockView from './components/Blocks/Gist/View';

import './theme/main.less';
import './theme/theme-dark.less';
import './theme/theme-light.less';
Expand Down Expand Up @@ -34,8 +40,8 @@ const applyConfig = (config) => {
title: 'Code Block',
icon: codeSVG,
group: 'text',
view: CodeBlockViewBlock,
edit: CodeBlockEditBlock,
view: CodeBlockView,
edit: CodeBlockEdit,
restricted: false,
mostUsed: false,
sidebarTab: 1,
Expand All @@ -57,6 +63,19 @@ const applyConfig = (config) => {
blockHasOwnFocusManagement: true,
};

config.blocks.blocksConfig.gistBlock = {
id: 'gistBlock',
title: 'Gist Block',
icon: codeSVG,
group: 'text',
view: GistBlockView,
edit: GistBlockEdit,
restricted: false,
mostUsed: false,
sidebarTab: 1,
blockHasOwnFocusManagement: false,
};

config.settings['codeBlock'] = {
languages: {
plain: { label: 'Plaintext', language: languages.plain },
Expand All @@ -76,11 +95,19 @@ const applyConfig = (config) => {
},
};

// Check for @kitconcept/volto-blocks-grid
const gridBlock = config.blocks.blocksConfig.__grid;
if (gridBlock !== undefined) {
config.blocks.blocksConfig.__grid.gridAllowedBlocks = [...gridBlock.gridAllowedBlocks, 'codeBlock', 'mermaidBlock'];
}
// Add Blocks to gridBlock and accordionBlock
['gridBlock', 'accordion'].forEach((blockId) => {
const block = config.blocks.blocksConfig[blockId];
if (block !== undefined) {
config.blocks.blocksConfig.gridBlock = {
...config.blocks.blocksConfig.gridBlock,
blocksConfig: {
...config.blocks.blocksConfig,
},
allowedBlocks: [...config.blocks.blocksConfig.gridBlock.allowedBlocks, 'codeBlock', 'mermaidBlock', 'gistBlock'],
};
}
});

return config;
};
Expand Down
Loading

0 comments on commit e0d368e

Please sign in to comment.