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
|
- Images, videos, and other non-text content is now wider in View Mode
|
||||||
- Notes may now be deleted directly from the history page
|
- 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
|
- 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
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,9 @@ https://www.youtube.com/watch?v=KgMpKsp23yY
|
||||||
## Vimeo
|
## Vimeo
|
||||||
https://vimeo.com/23237102
|
https://vimeo.com/23237102
|
||||||
|
|
||||||
|
## Asciinema
|
||||||
|
https://asciinema.org/a/117928
|
||||||
|
|
||||||
## PDF
|
## PDF
|
||||||
{%pdf https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.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 { 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 { 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'
|
||||||
import { replaceLegacySlideshareShortCode } from './regex-plugins/replace-legacy-slideshare-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 { replaceVimeoLink } from './regex-plugins/replace-vimeo-link'
|
||||||
import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
import { replaceYouTubeLink } from './regex-plugins/replace-youtube-link'
|
||||||
import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer'
|
import { ComponentReplacer, SubNodeConverter } from './replace-components/ComponentReplacer'
|
||||||
|
import { AsciinemaReplacer } from './replace-components/asciinema/asciinema-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'
|
||||||
|
@ -99,6 +101,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, cla
|
||||||
md.use(markdownItRegex, replaceLegacySlideshareShortCode)
|
md.use(markdownItRegex, replaceLegacySlideshareShortCode)
|
||||||
md.use(markdownItRegex, replaceLegacySpeakerdeckShortCode)
|
md.use(markdownItRegex, replaceLegacySpeakerdeckShortCode)
|
||||||
md.use(markdownItRegex, replacePdfShortCode)
|
md.use(markdownItRegex, replacePdfShortCode)
|
||||||
|
md.use(markdownItRegex, replaceAsciinemaLink)
|
||||||
md.use(markdownItRegex, replaceYouTubeLink)
|
md.use(markdownItRegex, replaceYouTubeLink)
|
||||||
md.use(markdownItRegex, replaceVimeoLink)
|
md.use(markdownItRegex, replaceVimeoLink)
|
||||||
md.use(markdownItRegex, replaceGistLink)
|
md.use(markdownItRegex, replaceGistLink)
|
||||||
|
@ -144,6 +147,7 @@ export const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({ content, cla
|
||||||
new GistReplacer(),
|
new GistReplacer(),
|
||||||
new YoutubeReplacer(),
|
new YoutubeReplacer(),
|
||||||
new VimeoReplacer(),
|
new VimeoReplacer(),
|
||||||
|
new AsciinemaReplacer(),
|
||||||
new PdfReplacer(),
|
new PdfReplacer(),
|
||||||
new ImageReplacer(),
|
new ImageReplacer(),
|
||||||
new TocReplacer(),
|
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 childIsImage = node.children[0].name === 'img'
|
||||||
const childIsYoutube = node.children[0].name === 'codimd-youtube'
|
const childIsYoutube = node.children[0].name === 'codimd-youtube'
|
||||||
const childIsVimeo = node.children[0].name === 'codimd-vimeo'
|
const childIsVimeo = node.children[0].name === 'codimd-vimeo'
|
||||||
|
const childIsAsciinema = node.children[0].name === 'codimd-asciinema'
|
||||||
const childIsPDF = node.children[0].name === 'codimd-pdf'
|
const childIsPDF = node.children[0].name === 'codimd-pdf'
|
||||||
if (!(childIsImage || childIsYoutube || childIsVimeo || childIsPDF)) {
|
if (!(childIsImage || childIsYoutube || childIsVimeo || childIsAsciinema || childIsPDF)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue