mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-24 18:56:32 -05:00
Added flowchart diagrams (#510)
Co-authored-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de> Co-authored-by: mrdrogdrog <mr.drogdrog@gmail.com> Co-authored-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
d482065d72
commit
33648f1645
8 changed files with 118 additions and 0 deletions
|
@ -41,6 +41,7 @@
|
|||
"eslint-plugin-node": "11.1.0",
|
||||
"eslint-plugin-promise": "4.2.1",
|
||||
"eslint-plugin-standard": "4.0.1",
|
||||
"flowchart.js": "1.14.0",
|
||||
"fork-awesome": "1.1.7",
|
||||
"github-markdown-css": "4.0.0",
|
||||
"highlight.js": "10.1.2",
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
"slogan": "The best platform to write and share markdown.",
|
||||
"title": "Collaborative markdown notes"
|
||||
},
|
||||
"renderer": {
|
||||
"flowchart": {
|
||||
"invalidSyntax": "Invalid flowchart.js syntax!"
|
||||
}
|
||||
},
|
||||
"landing": {
|
||||
"intro": {
|
||||
"exploreFeatures": "Explore all features",
|
||||
|
|
|
@ -9,6 +9,20 @@ opengraph:
|
|||
# Embedding demo
|
||||
[TOC]
|
||||
|
||||
## Flowchart
|
||||
|
||||
\`\`\`flow
|
||||
st=>start: Start
|
||||
e=>end: End
|
||||
op=>operation: My Operation
|
||||
op2=>operation: lalala
|
||||
cond=>condition: Yes or No?
|
||||
|
||||
st->op->op2->cond
|
||||
cond(yes)->e
|
||||
cond(no)->op2
|
||||
\`\`\`
|
||||
|
||||
## CSV
|
||||
|
||||
\`\`\`csv delimiter=; header
|
||||
|
|
|
@ -57,6 +57,7 @@ import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
|||
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-replacer'
|
||||
import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer'
|
||||
import { CsvReplacer } from './replace-components/csv/csv-replacer'
|
||||
import { FlowchartReplacer } from './replace-components/flow/flowchart-replacer'
|
||||
import { GistReplacer } from './replace-components/gist/gist-replacer'
|
||||
import { HighlightedCodeReplacer } from './replace-components/highlighted-fence/highlighted-fence-replacer'
|
||||
import { ImageReplacer } from './replace-components/image/image-replacer'
|
||||
|
@ -311,6 +312,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, onM
|
|||
new ImageReplacer(),
|
||||
new TocReplacer(),
|
||||
new CsvReplacer(),
|
||||
new FlowchartReplacer(),
|
||||
new HighlightedCodeReplacer(),
|
||||
new QuoteOptionsReplacer(),
|
||||
new KatexReplacer()
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
import { DomElement } from 'domhandler'
|
||||
import React from 'react'
|
||||
import { ComponentReplacer } from '../ComponentReplacer'
|
||||
import { FlowChart } from './flowchart/flowchart'
|
||||
|
||||
export class FlowchartReplacer implements ComponentReplacer {
|
||||
getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || codeNode.attribs['data-highlight-language'] !== 'flow' || !codeNode.children || !codeNode.children[0]) {
|
||||
return
|
||||
}
|
||||
|
||||
const code = codeNode.children[0].data as string
|
||||
|
||||
return <FlowChart key={`flowchart-${index}`} code={code}/>
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import { parse } from 'flowchart.js'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
import { Alert } from 'react-bootstrap'
|
||||
import { Trans, useTranslation } from 'react-i18next'
|
||||
|
||||
export interface FlowChartProps {
|
||||
code: string
|
||||
}
|
||||
|
||||
export const FlowChart: React.FC<FlowChartProps> = ({ code }) => {
|
||||
const diagramRef = useRef<HTMLDivElement>(null)
|
||||
const [error, setError] = useState(false)
|
||||
|
||||
useTranslation()
|
||||
|
||||
useEffect(() => {
|
||||
if (diagramRef.current === null) {
|
||||
return
|
||||
}
|
||||
const parserOutput = parse(code)
|
||||
try {
|
||||
parserOutput.drawSVG(diagramRef.current, {
|
||||
'line-width': 2,
|
||||
fill: 'none',
|
||||
'font-size': '16px',
|
||||
'font-family': 'Source Code Pro, twemoji, monospace'
|
||||
})
|
||||
setError(false)
|
||||
} catch (error) {
|
||||
setError(true)
|
||||
}
|
||||
|
||||
const currentDiagramRef = diagramRef.current
|
||||
|
||||
return () => {
|
||||
Array.from(currentDiagramRef.children).forEach(value => value.remove())
|
||||
}
|
||||
}, [code])
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Alert variant={'danger'}>
|
||||
<Trans i18nKey={'renderer.flowchart.invalidSyntax'}/>
|
||||
</Alert>
|
||||
)
|
||||
}
|
||||
return <div ref={diagramRef} className={'text-center'}/>
|
||||
}
|
13
src/external-types/flowchart.js/index.d.ts
vendored
Normal file
13
src/external-types/flowchart.js/index.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
declare module 'flowchart.js' {
|
||||
type Options = {
|
||||
'line-width': number,
|
||||
'fill': string,
|
||||
'font-size': string,
|
||||
'font-family': string
|
||||
}
|
||||
type ParseOutput = {
|
||||
clean: () => void,
|
||||
drawSVG: (container: HTMLElement, options: Options) => void,
|
||||
}
|
||||
export const parse: (code: string) => ParseOutput
|
||||
}
|
19
yarn.lock
19
yarn.lock
|
@ -5225,6 +5225,11 @@ etag@~1.8.1:
|
|||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||
|
||||
eve-raphael@0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eve-raphael/-/eve-raphael-0.5.0.tgz#17c754b792beef3fa6684d79cf5a47c63c4cda30"
|
||||
integrity sha1-F8dUt5K+7z+maE15z1pHxjxM2jA=
|
||||
|
||||
eventemitter2@^6.4.2:
|
||||
version "6.4.3"
|
||||
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.3.tgz#35c563619b13f3681e7eb05cbdaf50f56ba58820"
|
||||
|
@ -5659,6 +5664,13 @@ flatten@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
|
||||
integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
|
||||
|
||||
flowchart.js@1.14.0:
|
||||
version "1.14.0"
|
||||
resolved "https://registry.yarnpkg.com/flowchart.js/-/flowchart.js-1.14.0.tgz#b468501be54aa279bada8ec5da222e9eec542492"
|
||||
integrity sha512-XpXh6v2EUWJ1FyHdwFX1aZKLRpZXZmkMNcqVAV3dbIAmWGW++Oop31SpZRA/cJ8yaFjM16GZl/tb768fG8mBmg==
|
||||
dependencies:
|
||||
raphael "2.3.0"
|
||||
|
||||
flush-write-stream@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
|
||||
|
@ -10367,6 +10379,13 @@ range-parser@^1.2.1, range-parser@~1.2.1:
|
|||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raphael@2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/raphael/-/raphael-2.3.0.tgz#eabeb09dba861a1d4cee077eaafb8c53f3131f89"
|
||||
integrity sha512-w2yIenZAQnp257XUWGni4bLMVxpUpcIl7qgxEgDIXtmSypYtlNxfXWpOBxs7LBTps5sDwhRnrToJrMUrivqNTQ==
|
||||
dependencies:
|
||||
eve-raphael "0.5.0"
|
||||
|
||||
raw-body@2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
|
||||
|
|
Loading…
Reference in a new issue