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 '
';
});
}
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;