import ReactHtmlParser, { convertNodeToElement, type DomElement, type DomNode, type Transform, } from '@orrisroot/react-html-parser'; import type React from 'react'; import { HashLink } from 'react-router-hash-link'; import type { MultiLang } from '../../config'; import Functions from '../../functions'; interface Props { lang: MultiLang; text: string; dohtml?: boolean; dosmiley?: boolean; doxcode?: boolean; doimage?: boolean; dobr?: boolean; } const preConvertXCode = (text: string, doxcode: boolean): string => { if (doxcode) { return text.replace(/\[code\](.*)\[\/code\]/gs, (_m0, m1) => { return '[code]' + Functions.base64Encode(m1) + '[/code]'; }); } return text; }; const postConvertXCode = (text: string, doxcode: boolean, doimage: boolean): string => { if (doxcode) { return text.replace(/\[code\](.*)\[\/code\]/gs, (_m0, m1) => { const text = convertXCode(Functions.htmlspecialchars(Functions.base64Decode(m1)), doimage); return '
' + text + '
'; }); } return text; }; const convertClickable = (text: string) => { text = text.replace( /(^|[^\]_a-zA-Z0-9-="'/]+)((?:https?|ftp)(?::\/\/[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+[a-zA-Z0-9=]))/g, (...matches) => { return ( matches[1] + '' + matches[2] + '' ); }, ); text = text.replace( /(^|[^\]_a-zA-Z0-9-="'/:.]+)([a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+)/g, (...matches) => { return matches[1] + '' + matches[2] + ''; }, ); return text; }; const convertXCode = (text: string, _doimage: boolean): string => { // TODO: implement return text; }; const convertSmiley = (text: string) => { // TODO: implement return text; }; const convertBr = (text: string): string => { return text.replace(/(\r?\n|\r)/g, '
'); }; const cssConvert = (text: string): object => { const ret: any = {}; text.split(';').forEach((line) => { const line_ = line.trim(); if (line.length === 0) { return; } const kv = line_.split(':'); const key = Functions.camelCase(kv[0].trim()); const value = kv[1].trim(); ret[key] = value; }); return ret; }; const xoopsTransform: Transform = (node: DomNode, index: number | string, transform?: Transform): React.ReactNode => { if (node.type === 'tag') { const node_ = node as DomElement; if (node_.name === 'a') { const url = node_.attribs?.['href'] || '/'; const download = (node_.attribs && node_.attribs['download']) || ''; const rel = (node_.attribs && node_.attribs['rel']) || ''; const klass = (node_.attribs && node_.attribs['class']) || ''; const isFile = download !== '' || /\.(zip|pdf|png|gif|jpg)$/.test(url); const isExternal = /external/.test(rel) || /external/.test(klass) || /^(mailto|https?:?\/\/)/.test(url); if (!isFile && !isExternal) { const style = node_.attribs?.['style'] || ''; const title = node_.attribs?.['title']; return ( {node_.children.map((value: DomNode, index: number) => { return convertNodeToElement(value, index, transform); })} ); } } if (node_.name === 'img') { const src = (node_.attribs && node_.attribs['src']) || ''; node_.attribs['src'] = src.replace('`XOOPS_URL`', ''); return convertNodeToElement(node_, index, transform); } } }; const XoopsCode: React.FC = (props: Props) => { const { lang } = props; let text = props.text; const dohtml = !!props.dohtml; const dosmiley = !!props.dosmiley; const doxcode = !!props.doxcode; const doimage = !!props.doimage; const dobr = !!props.dobr; text = preConvertXCode(text, doxcode); if (!dohtml) { text = Functions.htmlspecialchars(text); text = convertClickable(text); } if (dosmiley) { text = convertSmiley(text); } if (doxcode) { text = convertXCode(text, doimage); } if (dobr) { text = convertBr(text); } text = postConvertXCode(text, doxcode, doimage); text = Functions.mlang(text, lang); return
{ReactHtmlParser(text, { transform: xoopsTransform })}
; }; export default XoopsCode;