mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-14 07:04:45 -04: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-node": "11.1.0",
|
||||||
"eslint-plugin-promise": "4.2.1",
|
"eslint-plugin-promise": "4.2.1",
|
||||||
"eslint-plugin-standard": "4.0.1",
|
"eslint-plugin-standard": "4.0.1",
|
||||||
|
"flowchart.js": "1.14.0",
|
||||||
"fork-awesome": "1.1.7",
|
"fork-awesome": "1.1.7",
|
||||||
"github-markdown-css": "4.0.0",
|
"github-markdown-css": "4.0.0",
|
||||||
"highlight.js": "10.1.2",
|
"highlight.js": "10.1.2",
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
"slogan": "The best platform to write and share markdown.",
|
"slogan": "The best platform to write and share markdown.",
|
||||||
"title": "Collaborative markdown notes"
|
"title": "Collaborative markdown notes"
|
||||||
},
|
},
|
||||||
|
"renderer": {
|
||||||
|
"flowchart": {
|
||||||
|
"invalidSyntax": "Invalid flowchart.js syntax!"
|
||||||
|
}
|
||||||
|
},
|
||||||
"landing": {
|
"landing": {
|
||||||
"intro": {
|
"intro": {
|
||||||
"exploreFeatures": "Explore all features",
|
"exploreFeatures": "Explore all features",
|
||||||
|
|
|
@ -9,6 +9,20 @@ opengraph:
|
||||||
# Embedding demo
|
# Embedding demo
|
||||||
[TOC]
|
[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
|
||||||
|
|
||||||
\`\`\`csv delimiter=; header
|
\`\`\`csv delimiter=; header
|
||||||
|
|
|
@ -57,6 +57,7 @@ import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
||||||
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-replacer'
|
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-replacer'
|
||||||
import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer'
|
import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer'
|
||||||
import { CsvReplacer } from './replace-components/csv/csv-replacer'
|
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 { GistReplacer } from './replace-components/gist/gist-replacer'
|
||||||
import { HighlightedCodeReplacer } from './replace-components/highlighted-fence/highlighted-fence-replacer'
|
import { HighlightedCodeReplacer } from './replace-components/highlighted-fence/highlighted-fence-replacer'
|
||||||
import { ImageReplacer } from './replace-components/image/image-replacer'
|
import { ImageReplacer } from './replace-components/image/image-replacer'
|
||||||
|
@ -311,6 +312,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, onM
|
||||||
new ImageReplacer(),
|
new ImageReplacer(),
|
||||||
new TocReplacer(),
|
new TocReplacer(),
|
||||||
new CsvReplacer(),
|
new CsvReplacer(),
|
||||||
|
new FlowchartReplacer(),
|
||||||
new HighlightedCodeReplacer(),
|
new HighlightedCodeReplacer(),
|
||||||
new QuoteOptionsReplacer(),
|
new QuoteOptionsReplacer(),
|
||||||
new KatexReplacer()
|
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"
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
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:
|
eventemitter2@^6.4.2:
|
||||||
version "6.4.3"
|
version "6.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.3.tgz#35c563619b13f3681e7eb05cbdaf50f56ba58820"
|
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"
|
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b"
|
||||||
integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==
|
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:
|
flush-write-stream@^1.0.0:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8"
|
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"
|
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
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:
|
raw-body@2.4.0:
|
||||||
version "2.4.0"
|
version "2.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
|
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue