const ESCAPED_OPENING_CHEVRON = '<';
const ESCAPED_CLOSING_CHEVRON = '>';
type Tags = {
transformed: {
opening: string;
closing: string;
};
escapedRegex: {
opening: RegExp;
closing: RegExp;
};
};
class EmphasisHtmlTransformer {
tags: Tags[];
constructor(whitelistedTags?: string[]) {
this.tags = (whitelistedTags || []).map((tag) => {
return {
transformed: {
opening: ``,
closing: '',
},
escapedRegex: {
opening: new RegExp(`${ESCAPED_OPENING_CHEVRON}${tag}${ESCAPED_CLOSING_CHEVRON}`, 'g'),
closing: new RegExp(`${ESCAPED_OPENING_CHEVRON}/${tag}${ESCAPED_CLOSING_CHEVRON}`, 'g'),
},
};
});
}
// Algorithm:
// 1) Escape all dangerous characters (<,>,&)
// 2) Replace all escaped, whitelisted tags with styled spans.
// 3) Transform new line characters to `
`s
//
// Note: for simplicity this doesn't support tags with non-standard whitespaces, e.g. positive>
transform(unsafe: string): string | null {
if (!unsafe) {
return null;
}
const safe = unsafe.replace(/&/g, '&').replace(//g, '>');
return this.tags
.reduce((accumulator, tag) => {
return accumulator
.replace(tag.escapedRegex.opening, tag.transformed.opening)
.replace(tag.escapedRegex.closing, tag.transformed.closing);
}, safe)
.replace(/\\n|\n/g, '
');
}
}
export default EmphasisHtmlTransformer;