diff --git a/asset-manifest.json b/asset-manifest.json index b8dd6ae..754dcda 100644 --- a/asset-manifest.json +++ b/asset-manifest.json @@ -1,15 +1,15 @@ { "files": { "main.css": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/css/main.f3484b48.chunk.css", - "main.js": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/main.f1f898b1.chunk.js", - "main.js.map": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/main.f1f898b1.chunk.js.map", + "main.js": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/main.e63d3d5a.chunk.js", + "main.js.map": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/main.e63d3d5a.chunk.js.map", "runtime~main.js": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/runtime~main.a9c024a1.js", "runtime~main.js.map": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/runtime~main.a9c024a1.js.map", "static/css/2.01da1c71.chunk.css": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/css/2.01da1c71.chunk.css", "static/js/2.8a1e8df3.chunk.js": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/2.8a1e8df3.chunk.js", "static/js/2.8a1e8df3.chunk.js.map": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/js/2.8a1e8df3.chunk.js.map", "index.html": "./index.html", - "precache-manifest.e883a1c193d9fd31443c2aa83909e879.js": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/precache-manifest.e883a1c193d9fd31443c2aa83909e879.js", + "precache-manifest.2206a1985ec160911961a60281c20730.js": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/precache-manifest.2206a1985ec160911961a60281c20730.js", "service-worker.js": "./service-worker.js", "static/css/2.01da1c71.chunk.css.map": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/css/2.01da1c71.chunk.css.map", "static/css/main.f3484b48.chunk.css.map": "//cdn.jsdelivr.net/gh/thuhole/webhole@gh-pages/static/css/main.f3484b48.chunk.css.map", diff --git a/index.html b/index.html index 0934ea3..4ef6303 100644 --- a/index.html +++ b/index.html @@ -1 +1 @@ -
'+de.a.highlight(t,e,!0).value+"
"}catch(n){}return''+pe.utils.escapeHtml(e)+"
"}}).use(ue.a,{throwOnError:!1,errorColor:"#aa0000"})),me=function(e){return pe.render(e)},fe="//thuhole.com/services/thuhole";function ge(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function be(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"g";return e?new RegExp("(".concat(e.split(t).filter(function(e){return!!e}).map(ge).join("|"),")"),n):/^$/g}function ve(e){return o.a.createElement("span",{className:"colored-span",style:{"--coloredspan-bgcolor-light":e.colors[0],"--coloredspan-bgcolor-dark":e.colors[1]}},e.children)}function Ee(e){return/^https?:\/\//.test(e)?e:"http://"+e}a.PureComponent;var _e=function(e){function t(){return Object(s.a)(this,t),Object(c.a)(this,Object(u.a)(t).apply(this,arguments))}return Object(d.a)(t,e),Object(l.a)(t,[{key:"render",value:function(){var e=this.props,t=[{shouldProcessNode:function(e){return"img"===e.name},processNode:function(e,t,n){return o.a.createElement("div",{key:n},"[\u56fe\u7247]")}},{shouldProcessNode:function(e){return/^h[123456]$/.test(e.name)},processNode:function(e,t,n){var a=+e.name[1];a<3&&(a=3);var r="h".concat(a);return o.a.createElement(r,{key:n},t)}},{shouldProcessNode:function(e){return"a"===e.name},processNode:function(e,t,n){return o.a.createElement("a",{href:Ee(e.attribs.href),target:"_blank",rel:"noopenner noreferrer",className:"ext-link",key:n},t,o.a.createElement("span",{className:"icon icon-new-tab"}))}},{shouldProcessNode:function(e){return"text"===e.type&&(!e.parent||!e.parent.attribs||"application/x-tex"!=e.parent.attribs.encoding)},processNode:function(t,n,a){var r=A(t.data,[["url_pid",E],["url",w],["pid",v],["nickname",_]]);return o.a.createElement(o.a.Fragment,{key:a},r.map(function(t,n){var a=Object(m.a)(t,2),r=a[0],i=a[1];return o.a.createElement("span",{key:n},"url_pid"===r?o.a.createElement("span",{className:"url-pid-link",title:i},"/##"):"url"===r?o.a.createElement("a",{href:Ee(i),className:"ext-link",target:"_blank",rel:"noopener noreferrer"},i,o.a.createElement("span",{className:"icon icon-new-tab"})):"pid"===r?o.a.createElement("a",{href:"#"+i,onClick:function(t){t.preventDefault(),e.show_pid(i.substring(1))}},i):"nickname"===r?o.a.createElement(ve,{colors:e.color_picker.get(i)},i):"search"===r?o.a.createElement("span",{className:"search-query-highlight"},i):i)}))}},{shouldProcessNode:function(){return!0},processNode:new ie.a.ProcessNodeDefinitions(o.a).processDefaultNode}],n=new ie.a.Parser;if(e.author&&e.text.match(/^(?:#+ |>|```|\t|\s*-|\s*\d+\.)/)){var a=me(e.text);return o.a.createElement(o.a.Fragment,null,e.author,n.parseWithInstructions(a,function(e){return"script"!==e.type},t)||"")}var r=e.text;e.author&&(r=e.author+" "+r);var i=me(r);return n.parseWithInstructions(i,function(e){return"script"!==e.type},t)||null}}]),t}(a.Component);window.TEXTAREA_BACKUP={};var we=function(e){function t(e){var n;return Object(s.a)(this,t),(n=Object(c.a)(this,Object(u.a)(t).call(this,e))).state={text:""},n.on_change_bound=n.on_change.bind(Object(h.a)(n)),n.on_keydown_bound=n.on_keydown.bind(Object(h.a)(n)),n.clear=n.clear.bind(Object(h.a)(n)),n.area_ref=o.a.createRef(),n.change_callback=e.on_change||function(){},n.submit_callback=e.on_submit||function(){},n}return Object(d.a)(t,e),Object(l.a)(t,[{key:"componentDidMount",value:function(){var e=this;this.setState({text:window.TEXTAREA_BACKUP[this.props.id]||""},function(){e.change_callback(e.state.text)})}},{key:"componentWillUnmount",value:function(){window.TEXTAREA_BACKUP[this.props.id]=this.state.text,this.change_callback(this.state.text)}},{key:"on_change",value:function(e){this.setState({text:e.target.value}),this.change_callback(e.target.value)}},{key:"on_keydown",value:function(e){"Enter"===e.key&&e.ctrlKey&&!e.altKey&&(e.preventDefault(),this.submit_callback())}},{key:"clear",value:function(){this.setState({text:""})}},{key:"set",value:function(e){this.change_callback(e),this.setState({text:e})}},{key:"get",value:function(){return this.state.text}},{key:"focus",value:function(){this.area_ref.current.focus()}},{key:"render",value:function(){return o.a.createElement("textarea",{ref:this.area_ref,onChange:this.on_change_bound,value:this.state.text,onKeyDown:this.on_keydown_bound})}}]),t}(a.Component),Ae=null;function ke(e){var t=/iPhone|iPad|iPod/i.test(window.navigator.userAgent);return window.matchMedia("(display-mode: standalone)").matches||window.navigator.standalone?null:t?navigator.standalone?null:o.a.createElement("div",{className:"box promotion-bar"},o.a.createElement("span",{className:"icon icon-about"}),"\xa0 \u7528 Safari \u628a\u6811\u6d1e ",o.a.createElement("b",null,"\u6dfb\u52a0\u5230\u4e3b\u5c4f\u5e55")," \u66f4\u597d\u7528"):Ae?o.a.createElement("div",{className:"box promotion-bar"},o.a.createElement("span",{className:"icon icon-about"}),"\xa0 \u628a\u7f51\u9875\u7248\u6811\u6d1e ",o.a.createElement("b",null,o.a.createElement("a",{onClick:function(){Ae&&Ae.prompt()}},"\u5b89\u88c5\u5230\u684c\u9762"))," \u66f4\u597d\u7528"):null}window.addEventListener("beforeinstallprompt",function(e){console.log("pwa: received before install prompt"),Ae=e});var ye=function(e){function t(e){var n;return Object(s.a)(this,t),(n=Object(c.a)(this,Object(u.a)(t).call(this,e))).state={moved:!0,init_y:0,init_x:0},n.on_begin_bound=n.on_begin.bind(Object(h.a)(n)),n.on_move_bound=n.on_move.bind(Object(h.a)(n)),n.on_end_bound=n.on_end.bind(Object(h.a)(n)),n.MOVE_THRESHOLD=3,n.last_fire=0,n}return Object(d.a)(t,e),Object(l.a)(t,[{key:"on_begin",value:function(e){this.setState({moved:!1,init_y:(e.touches?e.touches[0]:e).screenY,init_x:(e.touches?e.touches[0]:e).screenX})}},{key:"on_move",value:function(e){this.state.moved||Math.abs((e.touches?e.touches[0]:e).screenY-this.state.init_y)+Math.abs((e.touches?e.touches[0]:e).screenX-this.state.init_x)>this.MOVE_THRESHOLD&&this.setState({moved:!0})}},{key:"on_end",value:function(e){this.state.moved||this.do_callback(e),this.setState({moved:!0})}},{key:"do_callback",value:function(e){this.last_fire+100>+new Date||(this.last_fire=+new Date,this.props.callback(e))}},{key:"render",value:function(){return o.a.createElement("div",{onTouchStart:this.on_begin_bound,onMouseDown:this.on_begin_bound,onTouchMove:this.on_move_bound,onMouseMove:this.on_move_bound,onClick:this.on_end_bound},this.props.children)}}]),t}(a.PureComponent);n(427);function Oe(e,t,n,a){a=a||!1,e.addEventListener?e.addEventListener(t,n,a):e.attachEvent&&e.attachEvent("on".concat(t),function(t){n.call(e,t||window.event)})}function je(e,t,n,a){a=a||!1,e.removeEventListener?e.removeEventListener(t,n,a):e.detachEvent&&e.detachEvent("on".concat(t),n)}var Ce=function(e){if(!(e instanceof HTMLElement))return document.documentElement;for(var t="absolute"===e.style.position,n=/(scroll|auto)/,a=e;a;){if(!a.parentNode)return e.ownerDocument||document.documentElement;var o=window.getComputedStyle(a),r=o.position,i=o.overflow,s=o["overflow-x"],l=o["overflow-y"];if("static"===r&&t)a=a.parentNode;else{if(n.test(i)&&n.test(s)&&n.test(l))return a;a=a.parentNode}}return e.ownerDocument||e.documentElement||document.documentElement};var Ne=0,xe=0,Se="data-lazyload-listened",Ie=[],De=[],Ue=!1;try{var Re=Object.defineProperty({},"passive",{get:function(){Ue=!0}});window.addEventListener("test",null,Re)}catch(Ut){}var He,Te=!!Ue&&{capture:!1,passive:!0},Qe=function(e){var t=i.a.findDOMNode(e);if(t instanceof HTMLElement){var n=Ce(t);(e.props.overflow&&n!==t.ownerDocument&&n!==document&&n!==document.documentElement?function(e,t){var n,a,o=i.a.findDOMNode(e);try{var r=t.getBoundingClientRect();n=r.top,a=r.height}catch(Ut){n=Ne,a=xe}var s,l,c=window.innerHeight||document.documentElement.clientHeight,u=Math.max(n,0),h=Math.min(c,n+a)-u;try{var d=o.getBoundingClientRect();s=d.top,l=d.height}catch(Ut){s=Ne,l=xe}var p=s-u,m=Array.isArray(e.props.offset)?e.props.offset:[e.props.offset,e.props.offset];return p-m[0]<=h&&p+l+m[1]>=0}(e,n):function(e){var t,n,a=i.a.findDOMNode(e);if(!(a.offsetWidth||a.offsetHeight||a.getClientRects().length))return!1;try{var o=a.getBoundingClientRect();t=o.top,n=o.height}catch(Ut){t=Ne,n=xe}var r=window.innerHeight||document.documentElement.clientHeight,s=Array.isArray(e.props.offset)?e.props.offset:[e.props.offset,e.props.offset];return t-s[0]<=r&&t+n+s[1]>=0}(e))?e.state.visible&&!e.state.hidden||(e.props.once&&De.push(e),e.setState({visible:!0,hidden:!1})):e.props.once||(e.props.unmountIfInvisible?!0===e.visible&&e.setState({visible:!1}):e.props.hiddenIfInvisible&&!1===e.state.hidden&&e.setState({hidden:!0}))}},Me=function(){for(var e=0;e\n {props.text}\n
\n )\n}\n\nexport function GlobalTitle(props) {\n return (\n{props.text}
\n\n// {!!dropdown_cur_app ?\n// app_elem((()=>{\n// let [id,title,_url,icon_normal,icon_hover,_new_tab]=dropdown_cur_app;\n// return [id,title+'▾',null,icon_normal,icon_hover,false];\n// })(),true) :\n// app_elem(['-placeholder-elem','更多▾',null,appicon_dropdown,appicon_dropdown_rev,false],true)\n// }\n//
\n// {this.state.apps.dropdown.map((app)=>{\n// let ref=React.createRef();\n// return (\n//{\n// if(!e.target.closest('a') && ref.current)\n// ref.current.click();\n// }}>\n// {app_elem(app,true,ref)}\n//
\n// );\n// })}\n//\n 接收验证码来登录 T大树洞\n
\n\n \n \n {/*this.do_sendcode('sms')}>*/}\n {/* 短信 */}\n {/**/}\n {/*/*/}\n this.do_sendcode('mail')}>\n 发送邮件 \n \n \n
\n\n \n \n
\n\n 从其他设备导入登录状态\n
\n\n \n \n
\n\n \n
\n' +\n hljs.highlight(lang, str, true).value +\n '
';\n } catch (__) {}\n }\n return '' + md.utils.escapeHtml(str) + '
';\n }\n}).use(MarkdownItKaTeX, {\n \"throwOnError\" : false,\n \"errorColor\" : \"#aa0000\"\n})\n\nexport default (text) => md.render(text)","import React, {Component, PureComponent} from 'react';\nimport {format_time,Time,TitleLine} from './infrastructure/widgets';\nimport {THUHOLE_API_ROOT} from './flows_api';\n\nimport HtmlToReact from 'html-to-react'\n\nimport './Common.css';\nimport { URL_PID_RE, URL_RE, PID_RE, NICKNAME_RE, split_text } from './text_splitter';\n\nimport renderMd from './Markdown'\n\nexport {format_time,Time,TitleLine};\n\nexport const API_BASE=THUHOLE_API_ROOT+'services/thuhole';\n\n// https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex\nfunction escape_regex(string) {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // $& means the whole matched string\n}\n\nexport function build_highlight_re(txt,split,option='g') {\n return txt ? new RegExp(`(${txt.split(split).filter((x)=>!!x).map(escape_regex).join('|')})`,option) : /^$/g;\n}\n\nexport function ColoredSpan(props) {\n return (\n {props.children}\n )\n}\n\n\nfunction normalize_url(url) {\n return /^https?:\\/\\//.test(url) ? url : 'http://'+url;\n}\n\nexport class HighlightedText extends PureComponent {\n render() {\n return (\n \n {this.props.parts.map((part,idx)=>{\n let [rule,p]=part;\n return (\n {\n rule==='url_pid' ? /## :\n rule==='url' ? {p} :\n rule==='pid' ? {e.preventDefault(); this.props.show_pid(p.substring(1));}}>{p} :\n rule==='nickname' ? {p} :\n rule==='search' ? {p} :\n p\n }\n );\n })}\n
\n )\n }\n}\n\n// props: text, show_pid, color_picker\nexport class HighlightedMarkdown extends Component {\n render() {\n const props = this.props\n const processDefs = new HtmlToReact.ProcessNodeDefinitions(React)\n const processInstructions = [\n {\n shouldProcessNode: (node) => node.name === 'img', // disable images\n processNode (node, children, index) {\n return (正在下载……
);\n else if(this.state.state==='decoding')\n return (正在解码……
);\n else if(this.state.state==='loaded')\n return ();\n }\n}","import React, {Component, PureComponent} from 'react';\nimport {THUHOLE_API_ROOT, get_json, API_VERSION_PARAM} from './flows_api';\nimport {Time} from './Common';\n\nexport class MessageViewer extends PureComponent {\n constructor(props) {\n super(props);\n this.state={\n loading_status: 'idle',\n msg: [],\n };\n }\n\n componentDidMount() {\n this.load();\n }\n\n load() {\n if(this.state.loading_status==='loading') return;\n this.setState({\n loading_status: 'loading',\n },()=>{\n fetch(THUHOLE_API_ROOT+'api_xmcp/hole/system_msg?user_token='+encodeURIComponent(this.props.token)+API_VERSION_PARAM())\n .then(get_json)\n .then((json)=>{\n if(json.error)\n throw new Error(json.error);\n else\n this.setState({\n loading_status: 'done',\n msg: json.result,\n });\n })\n .catch((err)=>{\n console.error(err);\n alert(''+err);\n this.setState({\n loading_status: 'failed',\n });\n })\n\n });\n }\n\n render() {\n if(this.state.loading_status==='loading')\n return (加载中……
);\n else if(this.state.loading_status==='failed')\n return ();\n else if(this.state.loading_status==='done')\n return this.state.msg.map((msg)=>(\n{msg.content}\n
\n 背景图片:\n \n \n {img_select==='##other' &&\n \n }\n {img_select==='##color' &&\n \n }\n
\n \n\n 夜间模式:\n \n #color_scheme\n
\n\n 选择浅色或深色模式,深色模式下将会调暗图片亮度\n
\n\n \n
\n\n {this.props.description}\n
\n这些功能仍在测试,可能不稳定(全部重置)
\n修改设置后 {window.location.reload()}}>刷新页面 方可生效
\n\n {\n if('serviceWorker' in navigator) {\n navigator.serviceWorker.getRegistrations()\n .then((registrations)=>{\n for(let registration of registrations) {\n console.log('unregister',registration);\n registration.unregister();\n }\n });\n }\n cache().clear();\n setTimeout(()=>{\n window.location.reload(true);\n },200);\n }}>强制检查更新\n (当前版本:【{process.env.REACT_APP_BUILD_INFO||'---'} {process.env.NODE_ENV}】 会自动在后台检查更新并在下次访问时更新)\n
\n\n 联系我们:thuhole at protonmail dot com\n
\n\n T大树洞 网页版 by @thuhole,\n 基于 \n GPLv3\n 协议在 GitHub 开源\n
\n\n T大树洞 网页版的诞生离不开 \n P大树洞网页版 by @xmcp\n 、\n React\n 、\n IcoMoon\n 等开源项目\n
\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n
\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n GNU General Public License\n for more details.\n
\n\n 您已登录。\n \n
\n
*/}\n {/*根据计算中心要求,访问授权三个月内有效,过期需重新登录。*/}\n {/*T大树洞将会单向加密(i.e. 哈希散列)您的邮箱后再存入数据库,因此您的发帖具有较强的匿名性。具体可见我们的后端开源代码。*/}\n {/*
*/}\n\n {this.props.show_sidebar(\n '系统消息',\n
\n 当您发送的内容违规时,我们将用系统消息提示您\n
\n 复制 User Token
\n 复制 User Token 可以在新设备登录,切勿告知他人。若怀疑被盗号请重新邮箱验证码登录以重置Token。{/*,若怀疑被盗号请尽快
\n \n
\n\n T大树洞 面向T大学生,通过T大邮箱验证您的身份并提供服务。\n
\nload_single_meta(show_sidebar,token)(pid,true)}>重新加载
\n{''+e}
\n#{this.props.info.cid}
\n {!!this.props.do_filter_name &&\n {this.props.do_filter_name(this.props.info.name);}}>\n \n \n }\n \n {this.props.info.tag!==null &&\n \n {this.props.info.tag}\n \n }\n \n #{props.info.pid}
\n \n {(props.info.tag!==null && props.info.tag!=='折叠') &&\n \n {props.info.tag}\n \n }\n \n \n {props.img_clickable ?\n :\n
\n }\n
最新回复
\n }\n加载中……
);\n\n let show_pid=load_single_meta(this.props.show_sidebar,this.props.token);\n\n let replies_to_show=this.state.filter_name ? this.state.replies.filter((r)=>r.name===this.state.filter_name) : this.state.replies.slice();\n if(this.state.rev) replies_to_show.reverse();\n\n // key for lazyload elem\n let view_mode_key=(this.state.rev ? 'y-' : 'n-')+(this.state.filter_name||'null');\n\n let replies_cnt={[DZ_NAME]:1};\n replies_to_show.forEach((r)=>{\n if(replies_cnt[r.name]===undefined)\n replies_cnt[r.name]=0;\n replies_cnt[r.name]++;\n });\n\n // hide main thread when filtered\n let main_thread_elem=(this.state.filter_name && this.state.filter_name!==DZ_NAME) ? null : (\n\n {this.set_filter_name(null)}}>还原\n 当前只看 \n
回复加载失败
\n{this.state.error_msg}
\n{this.state.reply_error}
\n{this.state.error_msg}
\n{this.load_page(this.state.loaded_pages+1)}}>重新加载
\n{this.state.error_msg}
\n\n props.show_sidebar(\n 'T大树洞',\n
\n
'+de.a.highlight(t,e,!0).value+"
"}catch(n){}return''+pe.utils.escapeHtml(e)+"
"}}).use(ue.a,{throwOnError:!1,errorColor:"#aa0000"})),me=function(e){return pe.render(e)},fe="//thuhole.com/services/thuhole";function ge(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function be(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"g";return e?new RegExp("(".concat(e.split(t).filter(function(e){return!!e}).map(ge).join("|"),")"),n):/^$/g}function ve(e){return o.a.createElement("span",{className:"colored-span",style:{"--coloredspan-bgcolor-light":e.colors[0],"--coloredspan-bgcolor-dark":e.colors[1]}},e.children)}function Ee(e){return/^https?:\/\//.test(e)?e:"http://"+e}a.PureComponent;var _e=function(e){function t(){return Object(s.a)(this,t),Object(c.a)(this,Object(u.a)(t).apply(this,arguments))}return Object(d.a)(t,e),Object(l.a)(t,[{key:"render",value:function(){var e=this.props,t=[{shouldProcessNode:function(e){return"img"===e.name},processNode:function(e,t,n){return o.a.createElement("div",{key:n},"[\u56fe\u7247]")}},{shouldProcessNode:function(e){return/^h[123456]$/.test(e.name)},processNode:function(e,t,n){var a=+e.name[1];a<3&&(a=3);var r="h".concat(a);return o.a.createElement(r,{key:n},t)}},{shouldProcessNode:function(e){return"a"===e.name},processNode:function(e,t,n){return o.a.createElement("a",{href:Ee(e.attribs.href),target:"_blank",rel:"noopenner noreferrer",class:"ext-link",key:n},t,o.a.createElement("span",{className:"icon icon-new-tab"}))}},{shouldProcessNode:function(e){return"text"===e.type&&(!e.parent||!e.parent.attribs||"application/x-tex"!=e.parent.attribs.encoding)},processNode:function(t,n,a){var r=A(t.data,[["url_pid",E],["url",w],["pid",v],["nickname",_]]);return o.a.createElement(o.a.Fragment,{key:a},r.map(function(t,n){var a=Object(m.a)(t,2),r=a[0],i=a[1];return o.a.createElement("span",{key:n},"url_pid"===r?o.a.createElement("span",{className:"url-pid-link",title:i},"/##"):"url"===r?o.a.createElement("a",{href:Ee(i),class:"ext-link",target:"_blank",rel:"noopener noreferrer"},i,o.a.createElement("span",{className:"icon icon-new-tab"})):"pid"===r?o.a.createElement("a",{href:"#"+i,onClick:function(t){t.preventDefault(),e.show_pid(i.substring(1))}},i):"nickname"===r?o.a.createElement(ve,{colors:e.color_picker.get(i)},i):"search"===r?o.a.createElement("span",{className:"search-query-highlight"},i):i)}))}},{shouldProcessNode:function(){return!0},processNode:new ie.a.ProcessNodeDefinitions(o.a).processDefaultNode}],n=new ie.a.Parser;if(e.author&&e.text.match(/^(?:#+ |>|```|\t|\s*-|\s*\d+\.)/)){var a=me(e.text);return o.a.createElement(o.a.Fragment,null,e.author,n.parseWithInstructions(a,function(e){return"script"!==e.type},t)||"")}var r=e.text;e.author&&(r=e.author+" "+r);var i=me(r);return n.parseWithInstructions(i,function(e){return"script"!==e.type},t)||null}}]),t}(a.Component);window.TEXTAREA_BACKUP={};var we=function(e){function t(e){var n;return Object(s.a)(this,t),(n=Object(c.a)(this,Object(u.a)(t).call(this,e))).state={text:""},n.on_change_bound=n.on_change.bind(Object(h.a)(n)),n.on_keydown_bound=n.on_keydown.bind(Object(h.a)(n)),n.clear=n.clear.bind(Object(h.a)(n)),n.area_ref=o.a.createRef(),n.change_callback=e.on_change||function(){},n.submit_callback=e.on_submit||function(){},n}return Object(d.a)(t,e),Object(l.a)(t,[{key:"componentDidMount",value:function(){var e=this;this.setState({text:window.TEXTAREA_BACKUP[this.props.id]||""},function(){e.change_callback(e.state.text)})}},{key:"componentWillUnmount",value:function(){window.TEXTAREA_BACKUP[this.props.id]=this.state.text,this.change_callback(this.state.text)}},{key:"on_change",value:function(e){this.setState({text:e.target.value}),this.change_callback(e.target.value)}},{key:"on_keydown",value:function(e){"Enter"===e.key&&e.ctrlKey&&!e.altKey&&(e.preventDefault(),this.submit_callback())}},{key:"clear",value:function(){this.setState({text:""})}},{key:"set",value:function(e){this.change_callback(e),this.setState({text:e})}},{key:"get",value:function(){return this.state.text}},{key:"focus",value:function(){this.area_ref.current.focus()}},{key:"render",value:function(){return o.a.createElement("textarea",{ref:this.area_ref,onChange:this.on_change_bound,value:this.state.text,onKeyDown:this.on_keydown_bound})}}]),t}(a.Component),Ae=null;function ke(e){var t=/iPhone|iPad|iPod/i.test(window.navigator.userAgent);return window.matchMedia("(display-mode: standalone)").matches||window.navigator.standalone?null:t?navigator.standalone?null:o.a.createElement("div",{className:"box promotion-bar"},o.a.createElement("span",{className:"icon icon-about"}),"\xa0 \u7528 Safari \u628a\u6811\u6d1e ",o.a.createElement("b",null,"\u6dfb\u52a0\u5230\u4e3b\u5c4f\u5e55")," \u66f4\u597d\u7528"):Ae?o.a.createElement("div",{className:"box promotion-bar"},o.a.createElement("span",{className:"icon icon-about"}),"\xa0 \u628a\u7f51\u9875\u7248\u6811\u6d1e ",o.a.createElement("b",null,o.a.createElement("a",{onClick:function(){Ae&&Ae.prompt()}},"\u5b89\u88c5\u5230\u684c\u9762"))," \u66f4\u597d\u7528"):null}window.addEventListener("beforeinstallprompt",function(e){console.log("pwa: received before install prompt"),Ae=e});var ye=function(e){function t(e){var n;return Object(s.a)(this,t),(n=Object(c.a)(this,Object(u.a)(t).call(this,e))).state={moved:!0,init_y:0,init_x:0},n.on_begin_bound=n.on_begin.bind(Object(h.a)(n)),n.on_move_bound=n.on_move.bind(Object(h.a)(n)),n.on_end_bound=n.on_end.bind(Object(h.a)(n)),n.MOVE_THRESHOLD=3,n.last_fire=0,n}return Object(d.a)(t,e),Object(l.a)(t,[{key:"on_begin",value:function(e){this.setState({moved:!1,init_y:(e.touches?e.touches[0]:e).screenY,init_x:(e.touches?e.touches[0]:e).screenX})}},{key:"on_move",value:function(e){this.state.moved||Math.abs((e.touches?e.touches[0]:e).screenY-this.state.init_y)+Math.abs((e.touches?e.touches[0]:e).screenX-this.state.init_x)>this.MOVE_THRESHOLD&&this.setState({moved:!0})}},{key:"on_end",value:function(e){this.state.moved||this.do_callback(e),this.setState({moved:!0})}},{key:"do_callback",value:function(e){this.last_fire+100>+new Date||(this.last_fire=+new Date,this.props.callback(e))}},{key:"render",value:function(){return o.a.createElement("div",{onTouchStart:this.on_begin_bound,onMouseDown:this.on_begin_bound,onTouchMove:this.on_move_bound,onMouseMove:this.on_move_bound,onClick:this.on_end_bound},this.props.children)}}]),t}(a.PureComponent);n(427);function Oe(e,t,n,a){a=a||!1,e.addEventListener?e.addEventListener(t,n,a):e.attachEvent&&e.attachEvent("on".concat(t),function(t){n.call(e,t||window.event)})}function je(e,t,n,a){a=a||!1,e.removeEventListener?e.removeEventListener(t,n,a):e.detachEvent&&e.detachEvent("on".concat(t),n)}var Ce=function(e){if(!(e instanceof HTMLElement))return document.documentElement;for(var t="absolute"===e.style.position,n=/(scroll|auto)/,a=e;a;){if(!a.parentNode)return e.ownerDocument||document.documentElement;var o=window.getComputedStyle(a),r=o.position,i=o.overflow,s=o["overflow-x"],l=o["overflow-y"];if("static"===r&&t)a=a.parentNode;else{if(n.test(i)&&n.test(s)&&n.test(l))return a;a=a.parentNode}}return e.ownerDocument||e.documentElement||document.documentElement};var Ne=0,xe=0,Se="data-lazyload-listened",Ie=[],De=[],Ue=!1;try{var Re=Object.defineProperty({},"passive",{get:function(){Ue=!0}});window.addEventListener("test",null,Re)}catch(Ut){}var He,Te=!!Ue&&{capture:!1,passive:!0},Qe=function(e){var t=i.a.findDOMNode(e);if(t instanceof HTMLElement){var n=Ce(t);(e.props.overflow&&n!==t.ownerDocument&&n!==document&&n!==document.documentElement?function(e,t){var n,a,o=i.a.findDOMNode(e);try{var r=t.getBoundingClientRect();n=r.top,a=r.height}catch(Ut){n=Ne,a=xe}var s,l,c=window.innerHeight||document.documentElement.clientHeight,u=Math.max(n,0),h=Math.min(c,n+a)-u;try{var d=o.getBoundingClientRect();s=d.top,l=d.height}catch(Ut){s=Ne,l=xe}var p=s-u,m=Array.isArray(e.props.offset)?e.props.offset:[e.props.offset,e.props.offset];return p-m[0]<=h&&p+l+m[1]>=0}(e,n):function(e){var t,n,a=i.a.findDOMNode(e);if(!(a.offsetWidth||a.offsetHeight||a.getClientRects().length))return!1;try{var o=a.getBoundingClientRect();t=o.top,n=o.height}catch(Ut){t=Ne,n=xe}var r=window.innerHeight||document.documentElement.clientHeight,s=Array.isArray(e.props.offset)?e.props.offset:[e.props.offset,e.props.offset];return t-s[0]<=r&&t+n+s[1]>=0}(e))?e.state.visible&&!e.state.hidden||(e.props.once&&De.push(e),e.setState({visible:!0,hidden:!1})):e.props.once||(e.props.unmountIfInvisible?!0===e.visible&&e.setState({visible:!1}):e.props.hiddenIfInvisible&&!1===e.state.hidden&&e.setState({hidden:!0}))}},Me=function(){for(var e=0;e\n {props.text}\n
\n )\n}\n\nexport function GlobalTitle(props) {\n return (\n{props.text}
\n\n// {!!dropdown_cur_app ?\n// app_elem((()=>{\n// let [id,title,_url,icon_normal,icon_hover,_new_tab]=dropdown_cur_app;\n// return [id,title+'▾',null,icon_normal,icon_hover,false];\n// })(),true) :\n// app_elem(['-placeholder-elem','更多▾',null,appicon_dropdown,appicon_dropdown_rev,false],true)\n// }\n//
\n// {this.state.apps.dropdown.map((app)=>{\n// let ref=React.createRef();\n// return (\n//{\n// if(!e.target.closest('a') && ref.current)\n// ref.current.click();\n// }}>\n// {app_elem(app,true,ref)}\n//
\n// );\n// })}\n//\n 接收验证码来登录 T大树洞\n
\n\n \n \n {/*this.do_sendcode('sms')}>*/}\n {/* 短信 */}\n {/**/}\n {/*/*/}\n this.do_sendcode('mail')}>\n 发送邮件 \n \n \n
\n\n \n \n
\n\n 从其他设备导入登录状态\n
\n\n \n \n
\n\n \n
\n' +\n hljs.highlight(lang, str, true).value +\n '
';\n } catch (__) {}\n }\n return '' + md.utils.escapeHtml(str) + '
';\n }\n}).use(MarkdownItKaTeX, {\n \"throwOnError\" : false,\n \"errorColor\" : \"#aa0000\"\n})\n\nexport default (text) => md.render(text)","import React, {Component, PureComponent} from 'react';\nimport {format_time,Time,TitleLine} from './infrastructure/widgets';\nimport {THUHOLE_API_ROOT} from './flows_api';\n\nimport HtmlToReact from 'html-to-react'\n\nimport './Common.css';\nimport { URL_PID_RE, URL_RE, PID_RE, NICKNAME_RE, split_text } from './text_splitter';\n\nimport renderMd from './Markdown'\n\nexport {format_time,Time,TitleLine};\n\nexport const API_BASE=THUHOLE_API_ROOT+'services/thuhole';\n\n// https://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex\nfunction escape_regex(string) {\n return string.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'); // $& means the whole matched string\n}\n\nexport function build_highlight_re(txt,split,option='g') {\n return txt ? new RegExp(`(${txt.split(split).filter((x)=>!!x).map(escape_regex).join('|')})`,option) : /^$/g;\n}\n\nexport function ColoredSpan(props) {\n return (\n {props.children}\n )\n}\n\n\nfunction normalize_url(url) {\n return /^https?:\\/\\//.test(url) ? url : 'http://'+url;\n}\n\nexport class HighlightedText extends PureComponent {\n render() {\n return (\n \n {this.props.parts.map((part,idx)=>{\n let [rule,p]=part;\n return (\n {\n rule==='url_pid' ? /## :\n rule==='url' ? {p} :\n rule==='pid' ? {e.preventDefault(); this.props.show_pid(p.substring(1));}}>{p} :\n rule==='nickname' ? {p} :\n rule==='search' ? {p} :\n p\n }\n );\n })}\n
\n )\n }\n}\n\n// props: text, show_pid, color_picker\nexport class HighlightedMarkdown extends Component {\n render() {\n const props = this.props\n const processDefs = new HtmlToReact.ProcessNodeDefinitions(React)\n const processInstructions = [\n {\n shouldProcessNode: (node) => node.name === 'img', // disable images\n processNode (node, children, index) {\n return (正在下载……
);\n else if(this.state.state==='decoding')\n return (正在解码……
);\n else if(this.state.state==='loaded')\n return ();\n }\n}","import React, {Component, PureComponent} from 'react';\nimport {THUHOLE_API_ROOT, get_json, API_VERSION_PARAM} from './flows_api';\nimport {Time} from './Common';\n\nexport class MessageViewer extends PureComponent {\n constructor(props) {\n super(props);\n this.state={\n loading_status: 'idle',\n msg: [],\n };\n }\n\n componentDidMount() {\n this.load();\n }\n\n load() {\n if(this.state.loading_status==='loading') return;\n this.setState({\n loading_status: 'loading',\n },()=>{\n fetch(THUHOLE_API_ROOT+'api_xmcp/hole/system_msg?user_token='+encodeURIComponent(this.props.token)+API_VERSION_PARAM())\n .then(get_json)\n .then((json)=>{\n if(json.error)\n throw new Error(json.error);\n else\n this.setState({\n loading_status: 'done',\n msg: json.result,\n });\n })\n .catch((err)=>{\n console.error(err);\n alert(''+err);\n this.setState({\n loading_status: 'failed',\n });\n })\n\n });\n }\n\n render() {\n if(this.state.loading_status==='loading')\n return (加载中……
);\n else if(this.state.loading_status==='failed')\n return ();\n else if(this.state.loading_status==='done')\n return this.state.msg.map((msg)=>(\n{msg.content}\n
\n 背景图片:\n \n \n {img_select==='##other' &&\n \n }\n {img_select==='##color' &&\n \n }\n
\n \n\n 夜间模式:\n \n #color_scheme\n
\n\n 选择浅色或深色模式,深色模式下将会调暗图片亮度\n
\n\n \n
\n\n {this.props.description}\n
\n这些功能仍在测试,可能不稳定(全部重置)
\n修改设置后 {window.location.reload()}}>刷新页面 方可生效
\n\n {\n if('serviceWorker' in navigator) {\n navigator.serviceWorker.getRegistrations()\n .then((registrations)=>{\n for(let registration of registrations) {\n console.log('unregister',registration);\n registration.unregister();\n }\n });\n }\n cache().clear();\n setTimeout(()=>{\n window.location.reload(true);\n },200);\n }}>强制检查更新\n (当前版本:【{process.env.REACT_APP_BUILD_INFO||'---'} {process.env.NODE_ENV}】 会自动在后台检查更新并在下次访问时更新)\n
\n\n 联系我们:thuhole at protonmail dot com\n
\n\n T大树洞 网页版 by @thuhole,\n 基于 \n GPLv3\n 协议在 GitHub 开源\n
\n\n T大树洞 网页版的诞生离不开 \n P大树洞网页版 by @xmcp\n 、\n React\n 、\n IcoMoon\n 等开源项目\n
\n\n This program is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 3 of the License, or\n (at your option) any later version.\n
\n\n This program is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n GNU General Public License\n for more details.\n
\n\n 您已登录。\n \n
\n
*/}\n {/*根据计算中心要求,访问授权三个月内有效,过期需重新登录。*/}\n {/*T大树洞将会单向加密(i.e. 哈希散列)您的邮箱后再存入数据库,因此您的发帖具有较强的匿名性。具体可见我们的后端开源代码。*/}\n {/*
*/}\n\n {this.props.show_sidebar(\n '系统消息',\n
\n 当您发送的内容违规时,我们将用系统消息提示您\n
\n 复制 User Token
\n 复制 User Token 可以在新设备登录,切勿告知他人。若怀疑被盗号请重新邮箱验证码登录以重置Token。{/*,若怀疑被盗号请尽快
\n \n
\n\n T大树洞 面向T大学生,通过T大邮箱验证您的身份并提供服务。\n
\nload_single_meta(show_sidebar,token)(pid,true)}>重新加载
\n{''+e}
\n#{this.props.info.cid}
\n {!!this.props.do_filter_name &&\n {this.props.do_filter_name(this.props.info.name);}}>\n \n \n }\n \n {this.props.info.tag!==null &&\n \n {this.props.info.tag}\n \n }\n \n #{props.info.pid}
\n \n {(props.info.tag!==null && props.info.tag!=='折叠') &&\n \n {props.info.tag}\n \n }\n \n \n {props.img_clickable ?\n :\n
\n }\n
最新回复
\n }\n加载中……
);\n\n let show_pid=load_single_meta(this.props.show_sidebar,this.props.token);\n\n let replies_to_show=this.state.filter_name ? this.state.replies.filter((r)=>r.name===this.state.filter_name) : this.state.replies.slice();\n if(this.state.rev) replies_to_show.reverse();\n\n // key for lazyload elem\n let view_mode_key=(this.state.rev ? 'y-' : 'n-')+(this.state.filter_name||'null');\n\n let replies_cnt={[DZ_NAME]:1};\n replies_to_show.forEach((r)=>{\n if(replies_cnt[r.name]===undefined)\n replies_cnt[r.name]=0;\n replies_cnt[r.name]++;\n });\n\n // hide main thread when filtered\n let main_thread_elem=(this.state.filter_name && this.state.filter_name!==DZ_NAME) ? null : (\n\n {this.set_filter_name(null)}}>还原\n 当前只看 \n
回复加载失败
\n{this.state.error_msg}
\n{this.state.reply_error}
\n{this.state.error_msg}
\n{this.load_page(this.state.loaded_pages+1)}}>重新加载
\n{this.state.error_msg}
\n\n props.show_sidebar(\n 'T大树洞',\n
\n