Deduplicate code (#217)

* Deduplicate code

Signed-off-by: Tilman Vatteroth <tilman.vatteroth@tu-dortmund.de>
This commit is contained in:
mrdrogdrog 2020-06-20 20:32:44 +02:00 committed by GitHub
parent ab2a73c6a8
commit 5f4cc63eb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 40 deletions

View file

@ -12,7 +12,22 @@ import { TaskBar } from './task-bar/task-bar'
const Editor: React.FC = () => {
const editorMode: EditorMode = useSelector((state: ApplicationState) => state.editorConfig.editorMode)
const [markdownContent, setMarkdownContent] = useState('# Embedding demo\n\n## Slideshare\n{%slideshare mazlan1/internet-of-things-the-tip-of-an-iceberg %}\n\n## Gist\nhttps://gist.github.com/schacon/1\n\n## YouTube\nhttps://www.youtube.com/watch?v=KgMpKsp23yY\n\n## Vimeo\nhttps://vimeo.com/23237102\n\n## PDF\n{%pdf https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf %}')
const [markdownContent, setMarkdownContent] = useState(`
# Embedding demo
## Slideshare
{%slideshare mazlan1/internet-of-things-the-tip-of-an-iceberg %}
## Gist
https://gist.github.com/schacon/1
## YouTube
https://www.youtube.com/watch?v=KgMpKsp23yY
## Vimeo
https://vimeo.com/23237102
## PDF
{%pdf https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf %}`)
const isWide = useMedia({ minWidth: 576 })
const [firstDraw, setFirstDraw] = useState(true)

View file

@ -1,15 +1,16 @@
import { DomElement } from 'domhandler'
import MarkdownIt from 'markdown-it'
import abbreviation from 'markdown-it-abbr'
import markdownItContainer from 'markdown-it-container'
import definitionList from 'markdown-it-deflist'
import emoji from 'markdown-it-emoji'
import footnote from 'markdown-it-footnote'
import inserted from 'markdown-it-ins'
import marked from 'markdown-it-mark'
import markdownItRegex from 'markdown-it-regex'
import subscript from 'markdown-it-sub'
import superscript from 'markdown-it-sup'
import taskList from 'markdown-it-task-lists'
import footnote from 'markdown-it-footnote'
import React, { ReactElement, useMemo } from 'react'
import ReactHtmlParser, { convertNodeToElement, Transform } from 'react-html-parser'
import { createRenderContainer, validAlertLevels } from './container-plugins/alert'
@ -33,13 +34,25 @@ export interface MarkdownPreviewProps {
content: string
}
export type ComponentReplacer = (node: DomElement, counterMap: Map<string, number>) => (ReactElement | undefined);
const allComponentReplacers: ComponentReplacer[] = [getYouTubeReplacement, getVimeoReplacement, getGistReplacement, getPDFReplacement]
type ComponentReplacer2Identifier2CounterMap = Map<ComponentReplacer, Map<string, number>>
const tryToReplaceNode = (node: DomElement, componentReplacer2Identifier2CounterMap: ComponentReplacer2Identifier2CounterMap) => {
return allComponentReplacers
.map((componentReplacer) => {
const identifier2CounterMap = componentReplacer2Identifier2CounterMap.get(componentReplacer) || new Map<string, number>()
return componentReplacer(node, identifier2CounterMap)
})
.find((replacement) => !!replacement)
}
const MarkdownPreview: React.FC<MarkdownPreviewProps> = ({ content }) => {
const markdownIt = useMemo(() => {
const md = new MarkdownIt('default', {
html: true,
breaks: true,
langPrefix: '',
linkify: false,
typographer: true
})
md.use(taskList)
@ -70,36 +83,12 @@ const MarkdownPreview: React.FC<MarkdownPreviewProps> = ({ content }) => {
}, [])
const result: ReactElement[] = useMemo(() => {
const youtubeIdCounterMap = new Map<string, number>()
const vimeoIdCounterMap = new Map<string, number>()
const gistIdCounterMap = new Map<string, number>()
const componentReplacer2Identifier2CounterMap = new Map<ComponentReplacer, Map<string, number>>()
const html: string = markdownIt.render(content)
const transform: Transform = (node, index) => {
const resultYT = getYouTubeReplacement(node, youtubeIdCounterMap)
if (resultYT) {
return resultYT
}
const resultVimeo = getVimeoReplacement(node, vimeoIdCounterMap)
if (resultVimeo) {
return resultVimeo
}
const resultGist = getGistReplacement(node, gistIdCounterMap)
if (resultGist) {
return resultGist
}
const resultPdf = getPDFReplacement(node, gistIdCounterMap)
if (resultPdf) {
return resultPdf
}
return convertNodeToElement(node, index, transform)
return tryToReplaceNode(node, componentReplacer2Identifier2CounterMap) || convertNodeToElement(node, index, transform)
}
const ret: ReactElement[] = ReactHtmlParser(html, { transform: transform })
return ret
return ReactHtmlParser(html, { transform: transform })
}, [content, markdownIt])
return (

View file

@ -1,5 +1,5 @@
import { DomElement } from 'domhandler'
import React, { ReactElement, useCallback, useEffect, useMemo, useState } from 'react'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import { ComponentReplacer } from '../../markdown-preview'
import { OneClickEmbedding } from '../one-click-frame/one-click-embedding'
import { getIdFromCodiMdTag } from '../video-util'
import './gist-frame.scss'
@ -14,7 +14,7 @@ interface resizeEvent {
id: string
}
const getElementReplacement = (node: DomElement, counterMap: Map<string, number>): (ReactElement | undefined) => {
const getElementReplacement:ComponentReplacer = (node, counterMap) => {
const gistId = getIdFromCodiMdTag(node, 'gist')
if (gistId) {
const count = (counterMap.get(gistId) || 0) + 1

View file

@ -1,9 +1,9 @@
import { DomElement } from 'domhandler'
import React, { ReactElement, useCallback } from 'react'
import React, { useCallback } from 'react'
import { ComponentReplacer } from '../../markdown-preview'
import { OneClickEmbedding } from '../one-click-frame/one-click-embedding'
import { getIdFromCodiMdTag, VideoFrameProps } from '../video-util'
const getElementReplacement = (node: DomElement, counterMap: Map<string, number>): (ReactElement | undefined) => {
const getElementReplacement:ComponentReplacer = (node, counterMap) => {
const videoId = getIdFromCodiMdTag(node, 'vimeo')
if (videoId) {
const count = (counterMap.get(videoId) || 0) + 1

View file

@ -1,9 +1,9 @@
import { DomElement } from 'domhandler'
import React, { ReactElement } from 'react'
import React from 'react'
import { ComponentReplacer } from '../../markdown-preview'
import { OneClickEmbedding } from '../one-click-frame/one-click-embedding'
import { getIdFromCodiMdTag, VideoFrameProps } from '../video-util'
const getElementReplacement = (node: DomElement, counterMap: Map<string, number>): (ReactElement | undefined) => {
const getElementReplacement: ComponentReplacer = (node, counterMap) => {
const videoId = getIdFromCodiMdTag(node, 'youtube')
if (videoId) {
const count = (counterMap.get(videoId) || 0) + 1
@ -14,7 +14,9 @@ const getElementReplacement = (node: DomElement, counterMap: Map<string, number>
export const YouTubeFrame: React.FC<VideoFrameProps> = ({ id }) => {
return (
<OneClickEmbedding containerClassName={'embed-responsive embed-responsive-16by9'} previewContainerClassName={'embed-responsive-item'} hoverIcon={'youtube-play'} loadingImageUrl={`//i.ytimg.com/vi/${id}/maxresdefault.jpg`}>
<OneClickEmbedding containerClassName={'embed-responsive embed-responsive-16by9'}
previewContainerClassName={'embed-responsive-item'} hoverIcon={'youtube-play'}
loadingImageUrl={`//i.ytimg.com/vi/${id}/maxresdefault.jpg`}>
<iframe className='embed-responsive-item' title={`youtube video of ${id}`}
src={`//www.youtube-nocookie.com/embed/${id}?autoplay=1`}
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"/>