mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-14 07:04:45 -04:00
Remove keys from replacers (#539)
This commit is contained in:
parent
63b24fa5bf
commit
e58e53a116
20 changed files with 77 additions and 78 deletions
|
@ -1,10 +1,9 @@
|
|||
import { diffArrays } from 'diff'
|
||||
import { DomElement } from 'domhandler'
|
||||
import { ReactElement } from 'react'
|
||||
import React, { Fragment, ReactElement } from 'react'
|
||||
import { convertNodeToElement, Transform } from 'react-html-parser'
|
||||
import {
|
||||
ComponentReplacer,
|
||||
NativeRenderer,
|
||||
SubNodeTransform
|
||||
} from './replace-components/ComponentReplacer'
|
||||
|
||||
|
@ -75,9 +74,9 @@ export const calculateKeyFromLineMarker = (node: DomElement, lineKeys?: LineKeys
|
|||
return lineKeys[line].id
|
||||
}
|
||||
|
||||
export const findNodeReplacement = (node: DomElement, index: number, allReplacers: ComponentReplacer[], transform: SubNodeTransform, nativeRenderer: NativeRenderer): ReactElement|null|undefined => {
|
||||
export const findNodeReplacement = (node: DomElement, index: number, allReplacers: ComponentReplacer[], subNodeTransform: SubNodeTransform): ReactElement|null|undefined => {
|
||||
return allReplacers
|
||||
.map((componentReplacer) => componentReplacer.getReplacement(node, index, transform, nativeRenderer))
|
||||
.map((componentReplacer) => componentReplacer.getReplacement(node, subNodeTransform))
|
||||
.find((replacement) => replacement !== undefined)
|
||||
}
|
||||
|
||||
|
@ -96,13 +95,13 @@ export const buildTransformer = (lineKeys: (LineKeys[] | undefined), allReplacer
|
|||
const subNodeTransform:SubNodeTransform = (subNode, subIndex) => transform(subNode, subIndex, transform)
|
||||
|
||||
const key = calculateKeyFromLineMarker(node, lineKeys) ?? -index
|
||||
const tryReplacement = findNodeReplacement(node, key, allReplacers, subNodeTransform, nativeRenderer)
|
||||
const tryReplacement = findNodeReplacement(node, key, allReplacers, subNodeTransform)
|
||||
if (tryReplacement === null) {
|
||||
return null
|
||||
} else if (tryReplacement === undefined) {
|
||||
return nativeRenderer(node, key)
|
||||
} else {
|
||||
return tryReplacement
|
||||
return <Fragment key={key}>{tryReplacement}</Fragment>
|
||||
}
|
||||
}
|
||||
return transform
|
|
@ -1,10 +1,10 @@
|
|||
import { DomElement } from 'domhandler'
|
||||
import { ReactElement } from 'react'
|
||||
|
||||
export type SubNodeTransform = (node: DomElement, index: number) => ReactElement | void | null
|
||||
export type SubNodeTransform = (node: DomElement, subIndex: number) => ReactElement | void | null
|
||||
|
||||
export type NativeRenderer = (node: DomElement, key: number) => ReactElement
|
||||
|
||||
export abstract class ComponentReplacer {
|
||||
public abstract getReplacement(node: DomElement, index: number, subNodeTransform: SubNodeTransform, nativeRenderer: NativeRenderer): (ReactElement | null | undefined);
|
||||
public abstract getReplacement(node: DomElement, subNodeTransform: SubNodeTransform): (ReactElement | null | undefined);
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ import { ComponentReplacer } from '../ComponentReplacer'
|
|||
import { AbcFrame } from './abc-frame'
|
||||
|
||||
export class AbcReplacer implements ComponentReplacer {
|
||||
getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
getReplacement (codeNode: DomElement): React.ReactElement | undefined {
|
||||
if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || codeNode.attribs['data-highlight-language'] !== 'abc' || !codeNode.children || !codeNode.children[0]) {
|
||||
return
|
||||
}
|
||||
|
||||
const code = codeNode.children[0].data as string
|
||||
|
||||
return <AbcFrame key={'index'} code={code}/>
|
||||
return <AbcFrame code={code}/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ import { AsciinemaFrame } from './asciinema-frame'
|
|||
export class AsciinemaReplacer extends ComponentReplacer {
|
||||
private counterMap: Map<string, number> = new Map<string, number>()
|
||||
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const attributes = getAttributesFromHedgeDocTag(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 key={index} id={asciinemaId}/>
|
||||
<AsciinemaFrame id={asciinemaId}/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { ComponentReplacer } from '../ComponentReplacer'
|
|||
import { CsvTable } from './csv-table'
|
||||
|
||||
export class CsvReplacer extends ComponentReplacer {
|
||||
public getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (codeNode: DomElement): React.ReactElement | undefined {
|
||||
if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || codeNode.attribs['data-highlight-language'] !== 'csv' || !codeNode.children || !codeNode.children[0]) {
|
||||
return
|
||||
}
|
||||
|
@ -23,6 +23,6 @@ export class CsvReplacer extends ComponentReplacer {
|
|||
showHeader = extraInfos[3] !== undefined
|
||||
}
|
||||
|
||||
return <CsvTable key={`csv-${index}`} code={code} delimiter={delimiter} showHeader={showHeader}/>
|
||||
return <CsvTable code={code} delimiter={delimiter} showHeader={showHeader}/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ import { ComponentReplacer } from '../ComponentReplacer'
|
|||
import { FlowChart } from './flowchart/flowchart'
|
||||
|
||||
export class FlowchartReplacer extends ComponentReplacer {
|
||||
public getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (codeNode: DomElement): 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}/>
|
||||
return <FlowChart code={code}/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,14 @@ import preview from './gist-preview.png'
|
|||
export class GistReplacer extends ComponentReplacer {
|
||||
private counterMap: Map<string, number> = new Map<string, number>()
|
||||
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const attributes = getAttributesFromHedgeDocTag(node, 'gist')
|
||||
if (attributes && attributes.id) {
|
||||
const gistId = attributes.id
|
||||
const count = (this.counterMap.get(gistId) || 0) + 1
|
||||
this.counterMap.set(gistId, count)
|
||||
return (
|
||||
<OneClickEmbedding previewContainerClassName={'gist-frame'} key={index} loadingImageUrl={preview} hoverIcon={'github'} tooltip={'click to load gist'}>
|
||||
<OneClickEmbedding previewContainerClassName={'gist-frame'} loadingImageUrl={preview} hoverIcon={'github'} tooltip={'click to load gist'}>
|
||||
<GistFrame id={gistId}/>
|
||||
</OneClickEmbedding>
|
||||
)
|
||||
|
|
|
@ -6,7 +6,7 @@ import { HighlightedCode } from './highlighted-code/highlighted-code'
|
|||
export class HighlightedCodeReplacer extends ComponentReplacer {
|
||||
private lastLineNumber = 0;
|
||||
|
||||
public getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (codeNode: DomElement): React.ReactElement | undefined {
|
||||
if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || !codeNode.children || !codeNode.children[0]) {
|
||||
return
|
||||
}
|
||||
|
@ -33,6 +33,6 @@ export class HighlightedCodeReplacer extends ComponentReplacer {
|
|||
.filter(line => !!line).length
|
||||
}
|
||||
|
||||
return <HighlightedCode key={index} language={language} startLineNumber={showLineNumbers ? startLineNumber : undefined} wrapLines={wrapLines} code={code}/>
|
||||
return <HighlightedCode language={language} startLineNumber={showLineNumbers ? startLineNumber : undefined} wrapLines={wrapLines} code={code}/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,10 @@ import { ComponentReplacer } from '../ComponentReplacer'
|
|||
import { ImageFrame } from './image-frame'
|
||||
|
||||
export class ImageReplacer extends ComponentReplacer {
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
if (node.name === 'img' && node.attribs) {
|
||||
return <ImageFrame
|
||||
key={index}
|
||||
|
||||
id={node.attribs.id}
|
||||
className={node.attribs.class}
|
||||
src={node.attribs.src}
|
||||
|
|
|
@ -18,12 +18,12 @@ const getNodeIfInlineKatex = (node: DomElement): (DomElement|undefined) => {
|
|||
}
|
||||
|
||||
export class KatexReplacer extends ComponentReplacer {
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const katex = getNodeIfKatexBlock(node) || getNodeIfInlineKatex(node)
|
||||
if (katex?.children && katex.children[0]) {
|
||||
const mathJaxContent = katex.children[0]?.data as string
|
||||
const isInline = (katex.attribs?.inline) !== undefined
|
||||
return <TeX key={index} block={!isInline} math={mathJaxContent} errorColor={'#cc0000'}/>
|
||||
return <TeX block={!isInline} math={mathJaxContent} errorColor={'#cc0000'}/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { DomElement } from 'domhandler'
|
|||
import { ComponentReplacer } from '../ComponentReplacer'
|
||||
|
||||
export class LinemarkerReplacer extends ComponentReplacer {
|
||||
public getReplacement (codeNode: DomElement, index: number): null | undefined {
|
||||
public getReplacement (codeNode: DomElement): null | undefined {
|
||||
return codeNode.name === 'app-linemarker' ? null : undefined
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ import { ComponentReplacer } from '../ComponentReplacer'
|
|||
import { MermaidChart } from './mermaid-chart'
|
||||
|
||||
export class MermaidReplacer implements ComponentReplacer {
|
||||
getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
getReplacement (codeNode: DomElement): React.ReactElement | undefined {
|
||||
if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || codeNode.attribs['data-highlight-language'] !== 'mermaid' || !codeNode.children || !codeNode.children[0]) {
|
||||
return
|
||||
}
|
||||
|
||||
const code = codeNode.children[0].data as string
|
||||
|
||||
return <MermaidChart key={`flowchart-${index}`} code={code}/>
|
||||
return <MermaidChart code={code}/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import { PdfFrame } from './pdf-frame'
|
|||
export class PdfReplacer extends ComponentReplacer {
|
||||
private counterMap: Map<string, number> = new Map<string, number>()
|
||||
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const attributes = getAttributesFromHedgeDocTag(node, 'pdf')
|
||||
if (attributes && attributes.url) {
|
||||
const pdfUrl = attributes.url
|
||||
const count = (this.counterMap.get(pdfUrl) || 0) + 1
|
||||
this.counterMap.set(pdfUrl, count)
|
||||
return <PdfFrame key={index} url={pdfUrl}/>
|
||||
return <PdfFrame url={pdfUrl}/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { DomElement } from 'domhandler'
|
||||
import { ComponentReplacer, NativeRenderer, SubNodeTransform } from '../ComponentReplacer'
|
||||
import { ComponentReplacer } from '../ComponentReplacer'
|
||||
import './possible-wider-replacer.scss'
|
||||
|
||||
const enabledTags = ['img', 'app-youtube', 'app-vimeo', 'app-asciinema', 'app-pdf']
|
||||
|
@ -10,7 +10,7 @@ const enabledTags = ['img', 'app-youtube', 'app-vimeo', 'app-asciinema', 'app-pd
|
|||
* appends the "wider-possible" class to paragraphs with special content.
|
||||
*/
|
||||
export class PossibleWiderReplacer extends ComponentReplacer {
|
||||
public getReplacement (node: DomElement, index: number, subNodeTransformer: SubNodeTransform, nativeRenderer: NativeRenderer): (undefined) {
|
||||
public getReplacement (node: DomElement): (undefined) {
|
||||
if (node.name !== 'p') {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { DomElement } from 'domhandler'
|
||||
import { ReactElement } from 'react'
|
||||
import { ComponentReplacer, NativeRenderer, SubNodeTransform } from '../ComponentReplacer'
|
||||
import { ComponentReplacer } from '../ComponentReplacer'
|
||||
|
||||
const isColorExtraElement = (node: DomElement | undefined): boolean => {
|
||||
if (!node || !node.attribs || !node.attribs.class || !node.attribs['data-color']) {
|
||||
|
@ -19,7 +19,7 @@ const findQuoteOptionsParent = (nodes: DomElement[]): DomElement | undefined =>
|
|||
}
|
||||
|
||||
export class QuoteOptionsReplacer extends ComponentReplacer {
|
||||
public getReplacement (node: DomElement, index: number, subNodeTransform: SubNodeTransform, nativeRenderer: NativeRenderer):ReactElement|undefined {
|
||||
public getReplacement (node: DomElement):ReactElement|undefined {
|
||||
if (node.name !== 'blockquote' || !node.children || node.children.length < 1) {
|
||||
return
|
||||
}
|
||||
|
@ -38,6 +38,5 @@ export class QuoteOptionsReplacer extends ComponentReplacer {
|
|||
return
|
||||
}
|
||||
node.attribs = Object.assign(node.attribs || {}, { style: `border-left-color: ${attributes['data-color']};` })
|
||||
return nativeRenderer(node, index)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ import { MermaidChart } from '../mermaid/mermaid-chart'
|
|||
import { DeprecationWarning } from './deprecation-warning'
|
||||
|
||||
export class SequenceDiagramReplacer implements ComponentReplacer {
|
||||
getReplacement (codeNode: DomElement, index: number): React.ReactElement | undefined {
|
||||
getReplacement (codeNode: DomElement): React.ReactElement | undefined {
|
||||
if (codeNode.name !== 'code' || !codeNode.attribs || !codeNode.attribs['data-highlight-language'] || codeNode.attribs['data-highlight-language'] !== 'sequence' || !codeNode.children || !codeNode.children[0]) {
|
||||
return
|
||||
}
|
||||
|
||||
const code = codeNode.children[0].data as string
|
||||
|
||||
return <Fragment key={index} >
|
||||
return <Fragment>
|
||||
<DeprecationWarning/>
|
||||
<MermaidChart code={'sequenceDiagram\n' + code}/>
|
||||
</Fragment>
|
||||
|
|
|
@ -15,7 +15,7 @@ export class TaskListReplacer extends ComponentReplacer {
|
|||
this.onTaskCheckedChange(lineNum, event.currentTarget.checked)
|
||||
}
|
||||
|
||||
public getReplacement (node: DomElement, index:number): (ReactElement|undefined) {
|
||||
public getReplacement (node: DomElement): (ReactElement|undefined) {
|
||||
if (node.attribs?.class === 'task-list-item-checkbox') {
|
||||
return (
|
||||
<input
|
||||
|
@ -24,7 +24,6 @@ export class TaskListReplacer extends ComponentReplacer {
|
|||
checked={node.attribs.checked !== undefined}
|
||||
onChange={this.handleCheckboxChange}
|
||||
data-line={node.attribs['data-line']}
|
||||
key={`task-list-item-checkbox${node.attribs['data-line']}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import { VimeoFrame } from './vimeo-frame'
|
|||
export class VimeoReplacer extends ComponentReplacer {
|
||||
private counterMap: Map<string, number> = new Map<string, number>()
|
||||
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const attributes = getAttributesFromHedgeDocTag(node, 'vimeo')
|
||||
if (attributes && attributes.id) {
|
||||
const videoId = attributes.id
|
||||
const count = (this.counterMap.get(videoId) || 0) + 1
|
||||
this.counterMap.set(videoId, count)
|
||||
return <VimeoFrame key={index} id={videoId}/>
|
||||
return <VimeoFrame id={videoId}/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ import { YouTubeFrame } from './youtube-frame'
|
|||
export class YoutubeReplacer extends ComponentReplacer {
|
||||
private counterMap: Map<string, number> = new Map<string, number>()
|
||||
|
||||
public getReplacement (node: DomElement, index: number): React.ReactElement | undefined {
|
||||
public getReplacement (node: DomElement): React.ReactElement | undefined {
|
||||
const attributes = getAttributesFromHedgeDocTag(node, 'youtube')
|
||||
if (attributes && attributes.id) {
|
||||
const videoId = attributes.id
|
||||
const count = (this.counterMap.get(videoId) || 0) + 1
|
||||
this.counterMap.set(videoId, count)
|
||||
return <YouTubeFrame key={index} id={videoId}/>
|
||||
return <YouTubeFrame id={videoId}/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue