About the Code
The code is available at
About the Code
This plugin uses Remark Directive to convert ::pdf into a button (actually an a tag), and then processes PDF export within the component.
const activate = (): void => {
if (growiFacade == null || growiFacade.markdownRenderer == null) {
return;
}
const { optionsGenerators } = growiFacade.markdownRenderer;
const originalCustomViewOptions = optionsGenerators.customGenerateViewOptions;
optionsGenerators.customGenerateViewOptions = (...args) => {
const options = originalCustomViewOptions ? originalCustomViewOptions(...args) : optionsGenerators.generateViewOptions(...args);
// Convert Remark Directive into a button
options.remarkPlugins.push(remarkPlugin as any);
// Handle PDF export
const { a } = options.components;
options.components.a = pdfExport(a);
return options;
};
// For preview
const originalGeneratePreviewOptions = optionsGenerators.customGeneratePreviewOptions;
optionsGenerators.customGeneratePreviewOptions = (...args) => {
const preview = originalGeneratePreviewOptions ? originalGeneratePreviewOptions(...args) : optionsGenerators.generatePreviewOptions(...args);
preview.remarkPlugins.push(remarkPlugin as any);
const { a } = preview.components;
preview.components.a = pdfExport(a);
return preview;
};
};
Remark Directive Processing
Remark Directive handles the process of displaying the button at the top of the screen. A Node is added to hChildren.
export const remarkPlugin: Plugin = () => {
return (tree: Node) => {
visit(tree, 'leafDirective', (node: Node) => {
const n = node as unknown as GrowiNode;
if (n.name !== 'pdf') return;
const data = n.data || (n.data = {});
// Add a floating button to the top-right
data.hChildren = [
{
tagName: 'div',
type: 'element',
properties: { className: 'pdf-export-float-button' },
children: [
{
tagName: 'a',
type: 'element',
properties: { className: 'material-symbols-outlined me-1 grw-page-control-dropdown-icon pdf-export' },
children: [
{ type: 'text', value: 'cloud_download' },
],
},
],
},
];
});
};
};
This process adds the following DOM:
<div class="pdf-export-float-button">
<a class="material-symbols-outlined me-1 grw-page-control-dropdown-icon pdf-export">
cloud_download
</a>
</div>
Component Processing
Next, the component adds click handling to a.pdf-export.
export const pdfExport = (Tag: React.FunctionComponent<any>): React.FunctionComponent<any> => {
return ({ children, ...props }) => {
try {
// If the class is not `pdf-export`, process as a normal `a` tag
if (!props.className.split(' ').includes('pdf-export')) {
return (<a {...props}>{children}</a>);
}
// Click event
const onClick = async(e: MouseEvent) => {
};
// Add click event and return
return (
<a {...props} onClick={onClick}>{children}</a>
);
}
catch (err) {
// console.error(err);
}
// Return the original component if an error occurs
return (
<a {...props}>{children}</a>
);
};
};
Handling Button Clicks
The following is the content of the onClick function. The implementation supports multiple pages, based on
About the GROWI Community
If you have any questions or requests about using this plugin, feel free to reach out to the GROWI community. If feasible, I’ll try to accommodate your requests. There are also help channels available, so be sure to join!
SOCIAL SHARE CARD GENERATOR