Skip to content

Commit

Permalink
fix: fix uiwjs#38 by exporting unstyled components
Browse files Browse the repository at this point in the history
  • Loading branch information
samipourquoi committed Mar 27, 2021
1 parent 07ad1c1 commit 686f338
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 70 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package-lock.json
.cache
.rdoc-dist
.vscode
.idea

*.bak
*.tem
Expand Down
71 changes: 1 addition & 70 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,4 @@
import React, { useEffect, useImperativeHandle } from 'react';
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown';
import gfm from 'remark-gfm';
import Prism from 'prismjs';
import 'prismjs/components/prism-markup';
import { loadLang } from './langs';
import './styles/markdown.less';
import './styles/markdowncolor.less';

export type MarkdownPreviewProps = {
className?: string;
source?: string;
style?: React.CSSProperties;
onScroll?: (e: React.UIEvent<HTMLDivElement>) => void;
onMouseOver?: (e: React.MouseEvent<HTMLDivElement>) => void;
} & ReactMarkdownProps;

export type MarkdownPreviewRef = {
mdp: React.RefObject<HTMLDivElement>;
lang: string[],
} & MarkdownPreviewProps;

export default React.forwardRef<MarkdownPreviewRef, MarkdownPreviewProps>((props, ref) => {
const { className, source, style, onScroll, onMouseOver, ...other } = props || {};
const mdp = React.createRef<HTMLDivElement>();
const loadedLang = React.useRef<string[]>(['markup']);
useEffect(() => {
highlight();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [source]);

async function highlight() {
if (!mdp.current) return;
const codes = mdp.current.getElementsByTagName('code') as unknown as HTMLElement[];
for (const val of codes) {
const tag = val.parentNode as HTMLElement;
if (tag && tag.tagName === 'PRE' && /^language-/.test(val.className.trim())) {
const lang = val.className.trim().replace(/^language-/, '');
try {
if (!loadedLang.current.includes(lang as never)) {
loadedLang.current.push(lang);
await loadLang(lang);
}
await Prism.highlightElement(val);
} catch (error) { }
}
}
}

useImperativeHandle(ref, () => ({ ...props, lang: loadedLang.current, mdp }), [mdp, props]);

const cls = `wmde-markdown wmde-markdown-color ${className || ''}`;
const reactMarkdownProps = {
allowDangerousHtml: true,
allowNode: (node, index, parent) => {
if (node.type === 'html' && reactMarkdownProps.allowDangerousHtml) {
// filter style
node.value = (node.value as string).replace(/<((style|script|link|input|form)|\/(style|script|link|input|form))(\s?[^>]*>)/gi, (a: string) => {
return a.replace(/[<>]/g, (e: string) => (({ '<': '&lt;', '>': '&gt;' } as { [key: string]: string })[e]))
});
}
return true;
},
...other,
plugins: [gfm, ...(other.plugins || [])],
source: source || '',
} as ReactMarkdownProps;
return (
<div ref={mdp} onScroll={onScroll} onMouseOver={onMouseOver} className={cls} style={style}>
<ReactMarkdown {...reactMarkdownProps} />
</div>
);
});
export * from "unstyled";
71 changes: 71 additions & 0 deletions src/unstyled.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { useEffect, useImperativeHandle } from 'react';
import ReactMarkdown, { ReactMarkdownProps } from 'react-markdown';
import gfm from 'remark-gfm';
import Prism from 'prismjs';
import 'prismjs/components/prism-markup';
import { loadLang } from './langs';

export type MarkdownPreviewProps = {
className?: string;
source?: string;
style?: React.CSSProperties;
onScroll?: (e: React.UIEvent<HTMLDivElement>) => void;
onMouseOver?: (e: React.MouseEvent<HTMLDivElement>) => void;
} & ReactMarkdownProps;

export type MarkdownPreviewRef = {
mdp: React.RefObject<HTMLDivElement>;
lang: string[],
} & MarkdownPreviewProps;

export default React.forwardRef<MarkdownPreviewRef, MarkdownPreviewProps>((props, ref) => {
const { className, source, style, onScroll, onMouseOver, ...other } = props || {};
const mdp = React.createRef<HTMLDivElement>();
const loadedLang = React.useRef<string[]>(['markup']);
useEffect(() => {
highlight();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [source]);

async function highlight() {
if (!mdp.current) return;
const codes = mdp.current.getElementsByTagName('code') as unknown as HTMLElement[];
for (const val of codes) {
const tag = val.parentNode as HTMLElement;
if (tag && tag.tagName === 'PRE' && /^language-/.test(val.className.trim())) {
const lang = val.className.trim().replace(/^language-/, '');
try {
if (!loadedLang.current.includes(lang as never)) {
loadedLang.current.push(lang);
await loadLang(lang);
}
await Prism.highlightElement(val);
} catch (error) { }
}
}
}

useImperativeHandle(ref, () => ({ ...props, lang: loadedLang.current, mdp }), [mdp, props]);

const cls = `wmde-markdown wmde-markdown-color ${className || ''}`;
const reactMarkdownProps = {
allowDangerousHtml: true,
allowNode: (node, index, parent) => {
if (node.type === 'html' && reactMarkdownProps.allowDangerousHtml) {
// filter style
node.value = (node.value as string).replace(/<((style|script|link|input|form)|\/(style|script|link|input|form))(\s?[^>]*>)/gi, (a: string) => {
return a.replace(/[<>]/g, (e: string) => (({ '<': '&lt;', '>': '&gt;' } as { [key: string]: string })[e]))
});
}
return true;
},
...other,
plugins: [gfm, ...(other.plugins || [])],
source: source || '',
} as ReactMarkdownProps;
return (
<div ref={mdp} onScroll={onScroll} onMouseOver={onMouseOver} className={cls} style={style}>
<ReactMarkdown {...reactMarkdownProps} />
</div>
);
});

0 comments on commit 686f338

Please sign in to comment.