Browse Source

fixed markdown, tested

dev
Liu Jiangyi 5 years ago
parent
commit
e984dfeccb
  1. 62
      src/Common.js
  2. 10
      src/Flows.js
  3. 8
      src/Markdown.js

62
src/Common.js

@ -5,11 +5,9 @@ import {THUHOLE_API_ROOT} from './flows_api';
import HtmlToReact from 'html-to-react' import HtmlToReact from 'html-to-react'
import './Common.css'; import './Common.css';
import { URL_PID_RE, URL_RE, split_text } from './text_splitter'; import { URL_PID_RE, URL_RE, PID_RE, NICKNAME_RE, split_text } from './text_splitter';
import ProcessNodeDefinitions from 'html-to-react/lib/process-node-definitions';
import ReactMarkdown from 'react-markdown' import renderMd from './Markdown'
import htmlParser from 'react-markdown/plugins/html-parser'
export {format_time,Time,TitleLine}; export {format_time,Time,TitleLine};
@ -61,38 +59,20 @@ export class HighlightedText extends PureComponent {
} }
// props: text, show_pid, color_picker // props: text, show_pid, color_picker
export class HighlightedMarkdown extends PureComponent { export class HighlightedMarkdown extends Component {
render() { render() {
const props = this.props
const processDefs = new HtmlToReact.ProcessNodeDefinitions(React) const processDefs = new HtmlToReact.ProcessNodeDefinitions(React)
const astInst = [ const processInstructions = [
{ {
shouldProcessNode (node) { shouldProcessNode (node) {
return node.name === 'link' // urls return node.type === 'text' // pid, nickname, search
},
processNode (node) {
const originalHref = node.attribs.href
if (URL_PID_RE.test(originalHref)) { // url_pid
return (
<span className="url-pid-link" title={originalHref}>/##</span>
)
} else if (URL_RE.test(originalHref)) { // url
return (
<a href={normalize_url(originalHref)} target="_blank" rel="noopener">
{originalHref}
</a>
)
} else {// other cases are invalid, e.g. javascript:alert, etc
return (<a></a>)
}
}
},
{
shouldProcessNode (node) {
return node.name === 'text' // pid, nickname, search
}, },
processNode (node) { processNode (node) {
const originalText = node.data const originalText = node.data
const splitted = split_text(originalText, [ const splitted = split_text(originalText, [
['url_pid', URL_PID_RE],
['url',URL_RE],
['pid',PID_RE], ['pid',PID_RE],
['nickname',NICKNAME_RE], ['nickname',NICKNAME_RE],
]) ])
@ -100,12 +80,15 @@ export class HighlightedMarkdown extends PureComponent {
return ( return (
<> <>
{splitted.map(([rule, p], idx) => { {splitted.map(([rule, p], idx) => {
<span key={p}> return (<span key={idx}>
{rule==='pid' ? <a href={'#'+p} onClick={(e)=>{e.preventDefault(); this.props.show_pid(p.substring(1));}}>{p}</a> : {
rule==='nickname' ? <ColoredSpan colors={this.props.color_picker.get(p)}>{p}</ColoredSpan> : rule==='url_pid' ? <span className="url-pid-link" title={p}>/##</span> :
rule==='url' ? <a href={normalize_url(p)} target="_blank" rel="noopener">{p}</a> :
rule==='pid' ? <a href={'#'+p} onClick={(e)=>{e.preventDefault(); props.show_pid(p.substring(1));}}>{p}</a> :
rule==='nickname' ? <ColoredSpan colors={props.color_picker.get(p)}>{p}</ColoredSpan> :
rule==='search' ? <span className="search-query-highlight">{p}</span> : rule==='search' ? <span className="search-query-highlight">{p}</span> :
p} p}
</span> </span>)
})} })}
</> </>
) )
@ -116,16 +99,11 @@ export class HighlightedMarkdown extends PureComponent {
processNode: processDefs.processDefaultNode processNode: processDefs.processDefaultNode
} }
] ]
return ( const renderedMarkdown = renderMd(this.props.text)
<ReactMarkdown source={this.props.text} astPlugins={ const parser = new HtmlToReact.Parser()
[ console.log(`prerender:${renderedMarkdown}`)
htmlParser({
isValidNode(node) { return node.type !== 'script' }, return parser.parseWithInstructions(renderedMarkdown, node => node.type !== 'script', processInstructions)
processingInstructions: astInst
})
]
}/>
)
} }
} }

10
src/Flows.js

@ -7,7 +7,6 @@ import './Flows.css';
import LazyLoad from './react-lazyload/src'; import LazyLoad from './react-lazyload/src';
import {AudioWidget} from './AudioWidget'; import {AudioWidget} from './AudioWidget';
import {TokenCtx, ReplyForm} from './UserAction'; import {TokenCtx, ReplyForm} from './UserAction';
import renderMd from './Markdown'
import {API, THUHOLE_API_ROOT} from './flows_api'; import {API, THUHOLE_API_ROOT} from './flows_api';
@ -75,13 +74,6 @@ class Reply extends PureComponent {
} }
render() { render() {
let parts=split_text(this.props.info.text,[
['url_pid',URL_PID_RE],
['url',URL_RE],
['pid',PID_RE],
['nickname',NICKNAME_RE],
]);
return ( return (
<div className={'flow-reply box'} style={this.props.info._display_color ? { <div className={'flow-reply box'} style={this.props.info._display_color ? {
'--box-bgcolor-light': this.props.info._display_color[0], '--box-bgcolor-light': this.props.info._display_color[0],
@ -103,7 +95,7 @@ class Reply extends PureComponent {
<Time stamp={this.props.info.timestamp} /> <Time stamp={this.props.info.timestamp} />
</div> </div>
<div className="box-content"> <div className="box-content">
<HighlightedText parts={parts} color_picker={this.props.color_picker} show_pid={this.props.show_pid} /> <HighlightedMarkdown text={this.props.info.text} color_picker={this.props.color_picker} show_pid={this.props.show_pid} />
</div> </div>
</div> </div>
); );

8
src/Markdown.js

@ -0,0 +1,8 @@
import MarkdownIt from 'markdown-it'
let md = new MarkdownIt({
html: false,
linkify: false
})
export default (text) => md.render(text)
Loading…
Cancel
Save