mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 11:16:31 -05:00
Add Asciinema integration (#326)
* Added Asciinema integration * Added CHANGELOG entry
This commit is contained in:
parent
1b52bac838
commit
8216958f91
7 changed files with 68 additions and 1 deletions
|
@ -32,6 +32,7 @@
|
|||
- Images, videos, and other non-text content is now wider in View Mode
|
||||
- Notes may now be deleted directly from the history page
|
||||
- CodiMD instances can now be branded either with a '@ <custom string>' or '@ <custom logo>' after the CodiMD logo and text
|
||||
- Asciinema videos may now be embedded by pasting the URL of one video into a single line
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ https://www.youtube.com/watch?v=KgMpKsp23yY
|
|||
## Vimeo
|
||||
https://vimeo.com/23237102
|
||||
|
||||
## Asciinema
|
||||
https://asciinema.org/a/117928
|
||||
|
||||
## PDF
|
||||
{%pdf https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf %}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { highlightedCode } from './markdown-it-plugins/highlighted-code'
|
|||
import { linkifyExtra } from './markdown-it-plugins/linkify-extra'
|
||||
import { MarkdownItParserDebugger } from './markdown-it-plugins/parser-debugger'
|
||||
import './markdown-renderer.scss'
|
||||
import { replaceAsciinemaLink } from './regex-plugins/replace-asciinema-link'
|
||||
import { replaceGistLink } from './regex-plugins/replace-gist-link'
|
||||
import { replaceLegacyGistShortCode } from './regex-plugins/replace-legacy-gist-short-code'
|
||||
import { replaceLegacySlideshareShortCode } from './regex-plugins/replace-legacy-slideshare-short-code'
|
||||
|
@ -39,6 +40,7 @@ import { replaceQuoteExtraTime } from './regex-plugins/replace-quote-extra-time'
|
|||
import { replaceVimeoLink } from './regex-plugins/replace-vimeo-link'
|
||||
import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
||||
import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer'
|
||||
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-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'
|
||||
|
@ -99,6 +101,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, cla
|
|||
md.use(markdownItRegex, replaceLegacySlideshareShortCode)
|
||||
md.use(markdownItRegex, replaceLegacySpeakerdeckShortCode)
|
||||
md.use(markdownItRegex, replacePdfShortCode)
|
||||
md.use(markdownItRegex, replaceAsciinemaLink)
|
||||
md.use(markdownItRegex, replaceYouTubeLink)
|
||||
md.use(markdownItRegex, replaceVimeoLink)
|
||||
md.use(markdownItRegex, replaceGistLink)
|
||||
|
@ -144,6 +147,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, cla
|
|||
new GistReplacer(),
|
||||
new YoutubeReplacer(),
|
||||
new VimeoReplacer(),
|
||||
new AsciinemaReplacer(),
|
||||
new PdfReplacer(),
|
||||
new ImageReplacer(),
|
||||
new TocReplacer(),
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { RegexOptions } from '../../../../external-types/markdown-it-regex/interface'
|
||||
|
||||
const protocolRegex = /(?:http(?:s)?:\/\/)?/
|
||||
const domainRegex = /(?:asciinema\.org\/a\/)/
|
||||
const idRegex = /(\d+)/
|
||||
const tailRegex = /(?:[./?#].*)?/
|
||||
const gistUrlRegex = new RegExp(`(?:${protocolRegex.source}${domainRegex.source}${idRegex.source}${tailRegex.source})`)
|
||||
const linkRegex = new RegExp(`^${gistUrlRegex.source}$`, 'i')
|
||||
|
||||
export const replaceAsciinemaLink: RegexOptions = {
|
||||
name: 'asciinema-link',
|
||||
regex: linkRegex,
|
||||
replace: (match) => {
|
||||
// ESLint wants to collapse this tag, but then the tag won't be valid html anymore.
|
||||
// noinspection CheckTagEmptyBody
|
||||
return `<codimd-asciinema id="${match}"></codimd-asciinema>`
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
import React from 'react'
|
||||
import { OneClickEmbedding } from '../one-click-frame/one-click-embedding'
|
||||
|
||||
export interface AsciinemaFrameProps {
|
||||
id: string
|
||||
}
|
||||
|
||||
export const AsciinemaFrame: React.FC<AsciinemaFrameProps> = ({ id }) => {
|
||||
return (
|
||||
<OneClickEmbedding
|
||||
containerClassName={'embed-responsive embed-responsive-16by9'}
|
||||
previewContainerClassName={'embed-responsive-item'}
|
||||
hoverIcon={'play'}
|
||||
loadingImageUrl={`https://asciinema.org/a/${id}.png`}>
|
||||
<iframe className='embed-responsive-item' title={`asciinema cast ${id}`}
|
||||
src={`https://asciinema.org/a/${id}/embed?autoplay=1`}/>
|
||||
</OneClickEmbedding>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import { DomElement } from 'domhandler'
|
||||
import React from 'react'
|
||||
import { getAttributesFromCodiMdTag } from '../codi-md-tag-utils'
|
||||
import { ComponentReplacer } from '../ComponentReplacer'
|
||||
import { AsciinemaFrame } from './asciinema-frame'
|
||||
|
||||
export class AsciinemaReplacer implements ComponentReplacer {
|
||||
private counterMap: Map<string, number> = new Map<string, number>()
|
||||
|
||||
getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const attributes = getAttributesFromCodiMdTag(node, 'asciinema')
|
||||
if (attributes && attributes.id) {
|
||||
const asciinemaId = attributes.id
|
||||
const count = (this.counterMap.get(asciinemaId) || 0) + 1
|
||||
this.counterMap.set(asciinemaId, count)
|
||||
return (
|
||||
<AsciinemaFrame id={asciinemaId}/>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,8 +13,9 @@ export class PossibleWiderReplacer implements ComponentReplacer {
|
|||
const childIsImage = node.children[0].name === 'img'
|
||||
const childIsYoutube = node.children[0].name === 'codimd-youtube'
|
||||
const childIsVimeo = node.children[0].name === 'codimd-vimeo'
|
||||
const childIsAsciinema = node.children[0].name === 'codimd-asciinema'
|
||||
const childIsPDF = node.children[0].name === 'codimd-pdf'
|
||||
if (!(childIsImage || childIsYoutube || childIsVimeo || childIsPDF)) {
|
||||
if (!(childIsImage || childIsYoutube || childIsVimeo || childIsAsciinema || childIsPDF)) {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue