feat: add priorities for replacers

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2023-04-17 14:55:09 +02:00
parent 4a2cfe225c
commit a95b2d7d7d
4 changed files with 86 additions and 4 deletions

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import type { NodeReplacement } from '../../replace-components/component-replacer'
import { ComponentReplacer, DO_NOT_REPLACE } from '../../replace-components/component-replacer'
import { ComponentReplacer, DO_NOT_REPLACE, ReplacerPriority } from '../../replace-components/component-replacer'
import { NodeToReactTransformer } from './node-to-react-transformer'
import { Element } from 'domhandler'
import type { ReactElement, ReactHTMLElement } from 'react'
@ -37,6 +37,56 @@ describe('node to react transformer', () => {
expect(translation).toEqual(null)
})
it('will prioritize a high priority replacer over a normal priority replacer', () => {
nodeToReactTransformer.setReplacers([
new (class extends ComponentReplacer {
getPriority(): ReplacerPriority {
return ReplacerPriority.NORMAL
}
replace(): NodeReplacement {
return <span>Replacer O</span>
}
})(),
new (class extends ComponentReplacer {
getPriority(): ReplacerPriority {
return ReplacerPriority.HIGHER
}
replace(): NodeReplacement {
return <span>Replacer X</span>
}
})()
])
const translation = nodeToReactTransformer.translateNodeToReactElement(defaultTestSpanElement, 1) as ReactElement
expect(translation).toMatchSnapshot()
})
it('will prioritize a normal priority replacer over a low priority replacer', () => {
nodeToReactTransformer.setReplacers([
new (class extends ComponentReplacer {
getPriority(): ReplacerPriority {
return ReplacerPriority.LOWER
}
replace(): NodeReplacement {
return <span>Replacer M</span>
}
})(),
new (class extends ComponentReplacer {
getPriority(): ReplacerPriority {
return ReplacerPriority.NORMAL
}
replace(): NodeReplacement {
return <span>Replacer Y</span>
}
})()
])
const translation = nodeToReactTransformer.translateNodeToReactElement(defaultTestSpanElement, 1) as ReactElement
expect(translation).toMatchSnapshot()
})
it('can translate an element with no matching replacer', () => {
nodeToReactTransformer.setReplacers([
new (class extends ComponentReplacer {

View file

@ -31,7 +31,19 @@ export class NodeToReactTransformer {
}
public setReplacers(replacers: ComponentReplacer[]): void {
this.replacers = replacers
this.replacers = new Array(...replacers).sort(this.compareReplacers.bind(this))
}
private compareReplacers(replacerA: ComponentReplacer, replacerB: ComponentReplacer): number {
const priorityA = replacerA.getPriority()
const priorityB = replacerB.getPriority()
if (priorityA === priorityB) {
return 0
} else if (priorityA < priorityB) {
return -1
} else {
return 1
}
}
/**

View file

@ -17,6 +17,12 @@ export const DO_NOT_REPLACE = Symbol()
export type NodeReplacement = ValidReactDomElement | typeof DO_NOT_REPLACE
export enum ReplacerPriority {
LOWER = 1,
NORMAL = 0,
HIGHER = -1
}
/**
* Base class for all component replacers.
* Component replacers detect structures in the HTML DOM from markdown it
@ -65,4 +71,13 @@ export abstract class ComponentReplacer {
subNodeTransform: SubNodeTransform,
nativeRenderer: NativeRenderer
): NodeReplacement
/**
* Defines that a replacer should be preferred more or less than other replacers.
*
* @return the replacer priority that gets compared to others.
*/
public getPriority(): ReplacerPriority {
return ReplacerPriority.NORMAL
}
}

View file

@ -4,11 +4,12 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
import HighlightedCode from '../../../components/common/highlighted-code/highlighted-code'
import type { NodeReplacement } from '../../../components/markdown-renderer/replace-components/component-replacer'
import {
ComponentReplacer,
DO_NOT_REPLACE
DO_NOT_REPLACE,
ReplacerPriority
} from '../../../components/markdown-renderer/replace-components/component-replacer'
import type { NodeReplacement } from '../../../components/markdown-renderer/replace-components/component-replacer'
import type { Element } from 'domhandler'
import React from 'react'
@ -56,4 +57,8 @@ export class HighlightedCodeReplacer extends ComponentReplacer {
reset() {
this.lastLineNumber = 0
}
getPriority(): ReplacerPriority {
return ReplacerPriority.LOWER
}
}