diff --git a/src/Common.css b/src/Common.css index 9c11a6d..b1ca4eb 100644 --- a/src/Common.css +++ b/src/Common.css @@ -21,3 +21,7 @@ border-bottom: 1px solid black; font-weight: bold; } + +.url-pid-link { + opacity: .6; +} \ No newline at end of file diff --git a/src/Common.js b/src/Common.js index f2f43de..4f5a098 100644 --- a/src/Common.js +++ b/src/Common.js @@ -28,6 +28,7 @@ export class HighlightedText extends PureComponent { let [rule,p]=part; return ( { + rule==='url_pid' ? /hole/## : rule==='url' ? {p} : rule==='pid' ? {e.preventDefault(); this.props.show_pid(p);}}>{p} : rule==='nickname' ? {p} : diff --git a/src/Flows.js b/src/Flows.js index 9024564..bdec505 100644 --- a/src/Flows.js +++ b/src/Flows.js @@ -1,7 +1,7 @@ import React, {Component, PureComponent} from 'react'; import copy from 'copy-to-clipboard'; import {ColorPicker} from './color_picker'; -import {split_text,NICKNAME_RE,PID_RE,URL_RE} from './text_splitter'; +import {split_text, NICKNAME_RE, PID_RE, URL_RE, URL_PID_RE} from './text_splitter'; import {format_time, build_highlight_re, Time, TitleLine, HighlightedText, ClickHandler} from './Common'; import './Flows.css'; import LazyLoad from './react-lazyload/src'; @@ -70,6 +70,7 @@ class Reply extends PureComponent { render() { let parts=split_text(this.props.info.text,[ + ['url_pid',URL_PID_RE], ['url',URL_RE], ['pid',PID_RE], ['nickname',NICKNAME_RE], @@ -117,6 +118,7 @@ class FlowItem extends PureComponent { render() { let props=this.props; let parts=props.parts||split_text(props.info.text,[ + ['url_pid',URL_PID_RE], ['url',URL_RE], ['pid',PID_RE], ['nickname',NICKNAME_RE], @@ -468,6 +470,7 @@ class FlowItemRow extends PureComponent { let show_pid=load_single_meta(this.props.show_sidebar,this.props.token,[this.state.info.pid]); let hl_rules=[ + ['url_pid',URL_PID_RE], ['url',URL_RE], ['pid',PID_RE], ['nickname',NICKNAME_RE], diff --git a/src/text_splitter.js b/src/text_splitter.js index aeb800d..0e4ec18 100644 --- a/src/text_splitter.js +++ b/src/text_splitter.js @@ -1,4 +1,6 @@ +// regexp should match the WHOLE segmented part export const PID_RE=/(^|[^\d])([1-9]\d{4,5})(?!\d|\u20e3|\ufe0e|\ufe0f)/g; +export const URL_PID_RE=/((?:https?:\/\/)?pkuhelper\.pku\.edu\.cn\/hole\/?#(?:#|%23)([1-9]\d{4,5}))(?!\d|\u20e3|\ufe0e|\ufe0f)/g; export const NICKNAME_RE=/(^|[^A-Za-z])((?:(?:Angry|Baby|Crazy|Diligent|Excited|Fat|Greedy|Hungry|Interesting|Japanese|Kind|Little|Magic|Naïve|Old|Powerful|Quiet|Rich|Superman|THU|Undefined|Valuable|Wifeless|Xiangbuchulai|Young|Zombie)\s)?(?:Alice|Bob|Carol|Dave|Eve|Francis|Grace|Hans|Isabella|Jason|Kate|Louis|Margaret|Nathan|Olivia|Paul|Queen|Richard|Susan|Thomas|Uma|Vivian|Winnie|Xander|Yasmine|Zach)|You Win(?: \d+)?|洞主)(?![A-Za-z])/gi; export const URL_RE=/(^|[^.@a-zA-Z0-9_])((?:https?:\/\/)?(?:(?:[\w-]+\.)+[a-zA-Z]{2,3}|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::\d{1,5})?(?:\/[\w~!@#$%^&*()\-_=+[\];,./?]*)?)(?![a-zA-Z0-9])/gi; @@ -14,9 +16,14 @@ export function split_text(txt,rules) { if(rule) // already tagged by previous rules return [part]; else { - return content.split(regex).map((seg)=>( - regex.test(seg) ? [name,seg] : [null,seg] - )); + return content + .split(regex) + .map((seg)=>( + regex.test(seg) ? [name,seg] : [null,seg] + )) + .filter(([name,seg])=>( + name!==null || seg + )); } })); });