mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-17 00:24:43 -04:00
Add plantuml support (#327)
* Add plantuml support * Enable PlantUML rendering only if plantumlServer config is set * Show warning box when plantuml is enabled but no server is configured
This commit is contained in:
parent
c21503848f
commit
fe2f7403aa
11 changed files with 96 additions and 1 deletions
|
@ -58,6 +58,7 @@
|
||||||
"markdown-it-ins": "3.0.0",
|
"markdown-it-ins": "3.0.0",
|
||||||
"markdown-it-mark": "3.0.0",
|
"markdown-it-mark": "3.0.0",
|
||||||
"markdown-it-mathjax": "2.0.0",
|
"markdown-it-mathjax": "2.0.0",
|
||||||
|
"markdown-it-plantuml": "1.4.1",
|
||||||
"markdown-it-regex": "0.2.0",
|
"markdown-it-regex": "0.2.0",
|
||||||
"markdown-it-sub": "1.0.0",
|
"markdown-it-sub": "1.0.0",
|
||||||
"markdown-it-sup": "1.0.0",
|
"markdown-it-sup": "1.0.0",
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
"saml": "aufSAMLn.de"
|
"saml": "aufSAMLn.de"
|
||||||
},
|
},
|
||||||
"useImageProxy": false,
|
"useImageProxy": false,
|
||||||
|
"plantumlServer": "http://www.plantuml.com/plantuml",
|
||||||
"specialLinks": {
|
"specialLinks": {
|
||||||
"privacy": "https://example.com/privacy",
|
"privacy": "https://example.com/privacy",
|
||||||
"termsOfUse": "https://example.com/termsOfUse",
|
"termsOfUse": "https://example.com/termsOfUse",
|
||||||
|
|
|
@ -7,6 +7,7 @@ export interface Config {
|
||||||
useImageProxy: boolean,
|
useImageProxy: boolean,
|
||||||
specialLinks: SpecialLinks,
|
specialLinks: SpecialLinks,
|
||||||
version: BackendVersion,
|
version: BackendVersion,
|
||||||
|
plantumlServer: string | null,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BrandingConfig {
|
export interface BrandingConfig {
|
||||||
|
|
|
@ -52,4 +52,38 @@ https://asciinema.org/a/117928
|
||||||
|
|
||||||
let a = 1
|
let a = 1
|
||||||
\`\`\`
|
\`\`\`
|
||||||
|
|
||||||
|
## PlantUML
|
||||||
|
\`\`\`plantuml
|
||||||
|
@startuml
|
||||||
|
participant Alice
|
||||||
|
participant "The **Famous** Bob" as Bob
|
||||||
|
|
||||||
|
Alice -> Bob : hello --there--
|
||||||
|
... Some ~~long delay~~ ...
|
||||||
|
Bob -> Alice : ok
|
||||||
|
note left
|
||||||
|
This is **bold**
|
||||||
|
This is //italics//
|
||||||
|
This is ""monospaced""
|
||||||
|
This is --stroked--
|
||||||
|
This is __underlined__
|
||||||
|
This is ~~waved~~
|
||||||
|
end note
|
||||||
|
|
||||||
|
Alice -> Bob : A //well formatted// message
|
||||||
|
note right of Alice
|
||||||
|
This is <back:cadetblue><size:18>displayed</size></back>
|
||||||
|
__left of__ Alice.
|
||||||
|
end note
|
||||||
|
note left of Bob
|
||||||
|
<u:red>This</u> is <color #118888>displayed</color>
|
||||||
|
**<color purple>left of</color> <s:red>Alice</strike> Bob**.
|
||||||
|
end note
|
||||||
|
note over Alice, Bob
|
||||||
|
<w:#FF33FF>This is hosted</w> by <img sourceforge.jpg>
|
||||||
|
end note
|
||||||
|
@enduml
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import MarkdownIt, { Options } from 'markdown-it/lib'
|
||||||
|
import Renderer, { RenderRule } from 'markdown-it/lib/renderer'
|
||||||
|
import Token from 'markdown-it/lib/token'
|
||||||
|
|
||||||
|
export const plantumlError: MarkdownIt.PluginSimple = (md) => {
|
||||||
|
const defaultRenderer: RenderRule = md.renderer.rules.fence || (() => '')
|
||||||
|
md.renderer.rules.fence = (tokens: Token[], idx: number, options: Options, env, slf: Renderer) => {
|
||||||
|
const token = tokens[idx]
|
||||||
|
if (token.info === 'plantuml') {
|
||||||
|
return `
|
||||||
|
<p class="alert alert-danger">
|
||||||
|
PlantUML plugin is enabled but not properly configured.
|
||||||
|
</p>
|
||||||
|
`
|
||||||
|
}
|
||||||
|
return defaultRenderer(tokens, idx, options, env, slf)
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,11 @@
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& > img {
|
||||||
|
width: unset;
|
||||||
|
background-color: unset;
|
||||||
|
}
|
||||||
|
|
||||||
&.wider {
|
&.wider {
|
||||||
max-width: 1500px;
|
max-width: 1500px;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import inserted from 'markdown-it-ins'
|
||||||
import marked from 'markdown-it-mark'
|
import marked from 'markdown-it-mark'
|
||||||
import mathJax from 'markdown-it-mathjax'
|
import mathJax from 'markdown-it-mathjax'
|
||||||
import markdownItRegex from 'markdown-it-regex'
|
import markdownItRegex from 'markdown-it-regex'
|
||||||
|
import plantuml from 'markdown-it-plantuml'
|
||||||
import subscript from 'markdown-it-sub'
|
import subscript from 'markdown-it-sub'
|
||||||
import superscript from 'markdown-it-sup'
|
import superscript from 'markdown-it-sup'
|
||||||
import taskList from 'markdown-it-task-lists'
|
import taskList from 'markdown-it-task-lists'
|
||||||
|
@ -23,7 +24,9 @@ import { Alert } from 'react-bootstrap'
|
||||||
import ReactHtmlParser, { convertNodeToElement, Transform } from 'react-html-parser'
|
import ReactHtmlParser, { convertNodeToElement, Transform } from 'react-html-parser'
|
||||||
import { Trans } from 'react-i18next'
|
import { Trans } from 'react-i18next'
|
||||||
import MathJaxReact from 'react-mathjax'
|
import MathJaxReact from 'react-mathjax'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface'
|
import { TocAst } from '../../../external-types/markdown-it-toc-done-right/interface'
|
||||||
|
import { ApplicationState } from '../../../redux'
|
||||||
import { slugify } from '../../../utils/slugify'
|
import { slugify } from '../../../utils/slugify'
|
||||||
import { InternalLink } from '../../common/links/internal-link'
|
import { InternalLink } from '../../common/links/internal-link'
|
||||||
import { ShowIf } from '../../common/show-if/show-if'
|
import { ShowIf } from '../../common/show-if/show-if'
|
||||||
|
@ -33,6 +36,7 @@ import { highlightedCode } from './markdown-it-plugins/highlighted-code'
|
||||||
import { linkifyExtra } from './markdown-it-plugins/linkify-extra'
|
import { linkifyExtra } from './markdown-it-plugins/linkify-extra'
|
||||||
import { MarkdownItParserDebugger } from './markdown-it-plugins/parser-debugger'
|
import { MarkdownItParserDebugger } from './markdown-it-plugins/parser-debugger'
|
||||||
import './markdown-renderer.scss'
|
import './markdown-renderer.scss'
|
||||||
|
import { plantumlError } from './markdown-it-plugins/plantuml-error'
|
||||||
import { replaceAsciinemaLink } from './regex-plugins/replace-asciinema-link'
|
import { replaceAsciinemaLink } from './regex-plugins/replace-asciinema-link'
|
||||||
import { replaceGistLink } from './regex-plugins/replace-gist-link'
|
import { replaceGistLink } from './regex-plugins/replace-gist-link'
|
||||||
import { replaceLegacyGistShortCode } from './regex-plugins/replace-legacy-gist-short-code'
|
import { replaceLegacyGistShortCode } from './regex-plugins/replace-legacy-gist-short-code'
|
||||||
|
@ -93,6 +97,8 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, onM
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const plantumlServer = useSelector((state: ApplicationState) => state.config.plantumlServer)
|
||||||
|
|
||||||
const markdownIt = useMemo(() => {
|
const markdownIt = useMemo(() => {
|
||||||
const md = new MarkdownIt('default', {
|
const md = new MarkdownIt('default', {
|
||||||
html: true,
|
html: true,
|
||||||
|
@ -127,6 +133,15 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, onM
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
md.use(taskList)
|
md.use(taskList)
|
||||||
|
if (plantumlServer) {
|
||||||
|
md.use(plantuml, {
|
||||||
|
openMarker: '```plantuml',
|
||||||
|
closeMarker: '```',
|
||||||
|
server: plantumlServer
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
md.use(plantumlError)
|
||||||
|
}
|
||||||
md.use(emoji)
|
md.use(emoji)
|
||||||
md.use(abbreviation)
|
md.use(abbreviation)
|
||||||
md.use(definitionList)
|
md.use(definitionList)
|
||||||
|
@ -195,7 +210,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, onM
|
||||||
})
|
})
|
||||||
|
|
||||||
return md
|
return md
|
||||||
}, [onMetaDataChange, onFirstHeadingChange])
|
}, [onMetaDataChange, onFirstHeadingChange, plantumlServer])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (onTocChange && tocAst && !equal(tocAst, lastTocAst)) {
|
if (onTocChange && tocAst && !equal(tocAst, lastTocAst)) {
|
||||||
|
|
6
src/external-types/markdown-it-plantuml/index.d.ts
vendored
Normal file
6
src/external-types/markdown-it-plantuml/index.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
declare module 'markdown-it-plantuml' {
|
||||||
|
import MarkdownIt from 'markdown-it/lib'
|
||||||
|
import { PlantumlOptions } from './interface'
|
||||||
|
const markdownItPlantuml: MarkdownIt.PluginWithOptions<PlantumlOptions>
|
||||||
|
export = markdownItPlantuml
|
||||||
|
}
|
8
src/external-types/markdown-it-plantuml/interface.d.ts
vendored
Normal file
8
src/external-types/markdown-it-plantuml/interface.d.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import Renderer from 'markdown-it/lib/renderer'
|
||||||
|
|
||||||
|
export interface PlantumlOptions {
|
||||||
|
openMarker: string
|
||||||
|
closeMarker: string
|
||||||
|
render: Renderer
|
||||||
|
generateSource: (umlCode: string, pluginOptions: PlantumlOptions) => string
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ export const initialState: Config = {
|
||||||
saml: ''
|
saml: ''
|
||||||
},
|
},
|
||||||
useImageProxy: false,
|
useImageProxy: false,
|
||||||
|
plantumlServer: null,
|
||||||
specialLinks: {
|
specialLinks: {
|
||||||
privacy: '',
|
privacy: '',
|
||||||
termsOfUse: '',
|
termsOfUse: '',
|
||||||
|
|
|
@ -8096,6 +8096,11 @@ markdown-it-mathjax@2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz#ae2b4f4c5c719a03f9e475c664f7b2685231d9e9"
|
resolved "https://registry.yarnpkg.com/markdown-it-mathjax/-/markdown-it-mathjax-2.0.0.tgz#ae2b4f4c5c719a03f9e475c664f7b2685231d9e9"
|
||||||
integrity sha1-ritPTFxxmgP55HXGZPeyaFIx2ek=
|
integrity sha1-ritPTFxxmgP55HXGZPeyaFIx2ek=
|
||||||
|
|
||||||
|
markdown-it-plantuml@1.4.1:
|
||||||
|
version "1.4.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/markdown-it-plantuml/-/markdown-it-plantuml-1.4.1.tgz#3bd5e7d92eaa5c6c68eb29802f7b46a8e05ca998"
|
||||||
|
integrity sha512-13KgnZaGYTHBp4iUmGofzZSBz+Zj6cyqfR0SXUIc9wgWTto5Xhn7NjaXYxY0z7uBeTUMlc9LMQq5uP4OM5xCHg==
|
||||||
|
|
||||||
markdown-it-regex@0.2.0:
|
markdown-it-regex@0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/markdown-it-regex/-/markdown-it-regex-0.2.0.tgz#e09ad2d75209720d591d3949e1142c75c0fbecf6"
|
resolved "https://registry.yarnpkg.com/markdown-it-regex/-/markdown-it-regex-0.2.0.tgz#e09ad2d75209720d591d3949e1142c75c0fbecf6"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue