diff --git a/adblock/index.html b/adblock/index.html index e69de29..004e8c8 100644 --- a/adblock/index.html +++ b/adblock/index.html @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + 广告屏蔽技术总览 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 广告屏蔽技术总览 +
+ + +
+

超微浏览器提供了形形色色的广告屏蔽技术,善于使用的话根本无需求助于复杂的屏蔽规则。

+ + +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/adblock_css/index.html b/adblock_css/index.html index e69de29..01edd16 100644 --- a/adblock_css/index.html +++ b/adblock_css/index.html @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + 利用用户自定义样式屏蔽广告 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用用户自定义样式屏蔽广告 +
+ + +
+

超微浏览器支持超级hosts文件,这一技术可以完全绝杀手机广告小厂。但少部分广告大厂本身也提供高质量的内容服务,它们可以将广告伪装成正常的内容从而逃脱hosts文件绝杀。
对这一部分广告而言,我们可以利用超微浏览器的自定义样式功能加以屏蔽。

+

下载下面文件(可改名成“广告屏蔽.css”),将其放到/scard/uweb/css目录下:
广告屏蔽css文件

+

重启浏览器,长按底部工具条[☰]按钮弹出对话框后勾选上述文件名即可屏蔽广告。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/adblock_hosts/index.html b/adblock_hosts/index.html index e69de29..fb148d3 100644 --- a/adblock_hosts/index.html +++ b/adblock_hosts/index.html @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + 利用超级hosts绝杀广告 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用超级hosts绝杀广告 +
+ + +
+

超级hosts文件可屏蔽文件中域名的一切子域名、孙域名、……,可彻底绝杀一切广告。所以用户屏蔽根域名时无需选择提示中出现的整个域名,只需选取最后两段或三段(少数很短的域名可取四段)。

+
    +
  • 长按广告链接,点击“图片:屏蔽根域名”,修改弹出域名,一般取最后两段,点击”确定”屏蔽当前图片网址。
  • +
  • 部分广告没有链接可长按,或虽有链接但长按时不出现图片相关菜单。此时可长按[JS]点击”背景图片”或”看图模式”,再长按广告链接点击“图片:屏蔽根域名”,屏蔽图片网址。
  • +
  • 可长按设置开启”资源嗅探”,推荐设置文件”/sdcard/uweb/types.sniff”内容为js,刷新网页后关闭”资源嗅探”选项。在弹出的资源网页上长按链接,屏蔽根域名。
  • +
  • (可选) 长按广告链接,点击“屏蔽根域名”,屏蔽链接网址。

    +
  • +
  • (可选) 某些广告靠javascript激发,链接中不出现域名,可点击激发至新网址后将新网址根域名屏蔽。

    +
  • +
  • 超级hosts文件支持域名及整个网址正则表达式
    default.hosts文件格式每行如下:
    根域名[空格]域名前缀正则表达式[空格]网址路径正则表达式
    空格及后面两个正则表达式为可选择项。

    +
  • +
+

部分国内大厂广告 (将下列内容放入/sdcard/uweb/default.hosts,点击本链接自动用以下内容覆盖default.hosts):
lianmeng.360.cn
appjiagu.com
adm-cnzz.net
alimama.com
ipinyou.com
mct01.com
tanx.com
wrating.com
cpro.baidu.com
pos.baidu.com
share.baidu.com
e.qq.com
gdt.qq.com
l.qq.com
push.qq.com
beacon.sina.com.cn
mix.sina.com.cn
go.sohu.com
inte.sogou.com
epro.sogou.com
golden1.sogou.com
uranus.sogou.com
inte.sogoucdn.com
lu.sogoucdn.com
theta.sogoucdn.com
ad.xiaomi.com

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2019/06/index.html b/archives/2019/06/index.html index e69de29..729e05d 100644 --- a/archives/2019/06/index.html +++ b/archives/2019/06/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2019/11/index.html b/archives/2019/11/index.html index e69de29..729e05d 100644 --- a/archives/2019/11/index.html +++ b/archives/2019/11/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2019/index.html b/archives/2019/index.html index e69de29..729e05d 100644 --- a/archives/2019/index.html +++ b/archives/2019/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2020/01/index.html b/archives/2020/01/index.html index e69de29..729e05d 100644 --- a/archives/2020/01/index.html +++ b/archives/2020/01/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2020/03/index.html b/archives/2020/03/index.html index e69de29..729e05d 100644 --- a/archives/2020/03/index.html +++ b/archives/2020/03/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2020/04/index.html b/archives/2020/04/index.html index e69de29..729e05d 100644 --- a/archives/2020/04/index.html +++ b/archives/2020/04/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/2020/index.html b/archives/2020/index.html index e69de29..729e05d 100644 --- a/archives/2020/index.html +++ b/archives/2020/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/archives/index.html b/archives/index.html index e69de29..729e05d 100644 --- a/archives/index.html +++ b/archives/index.html @@ -0,0 +1,516 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + + + +
+ +
+ + 2020 + + +
+ + + +
+
+
+ + + + + + + + + + + + + + + + diff --git a/bc/index.html b/bc/index.html index e69de29..01d7a3d 100644 --- a/bc/index.html +++ b/bc/index.html @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + 配置浏览器地址栏作为超级计算器(bc) + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 配置浏览器地址栏作为超级计算器(bc) +
+ + +
+

使用Android端uweb浏览器
Gnu bc计算器支持无限精度,可轻易扩展函数库、常数库。

+

安装bc

+ + +

配置文件/sdcard/uweb/default.acmd如下:

计算器:text/html:echo “%s”|bc -l -q

+

更多bc扩展库:

扩展库可下载至/sdcard/uweb目录)
https://github.com/susca/bc-extensions
http://phodd.net/gnu-bc
http://www.numbertheory.org/gnubc/gnubc.html

+

使用扩展库以后default.acmd配置如下:

计算器:text/html:echo “%s”|bc -l -q extensions.bc scientific_constants.bc
全能计算器:text/html:echo “%s”|bc -l -q *.bc

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/bookmarklet/index.html b/bookmarklet/index.html index e69de29..610a106 100644 --- a/bookmarklet/index.html +++ b/bookmarklet/index.html @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + 小书签 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 小书签 +
+ + +
+

超微浏览器支持直接运行远程网址上的小书签(Bookmarklet),将本页面或其它包含小书签网址加入书签。使用时只需长按小书签链接,点击“新窗口打开”,小书签将作用于超微浏览器最后一个窗口(非小书签窗口)页面上。

+

查看浏览器UA
网页源码
显示网页最后更改时间
切换复选框状态
解除选择复制限制(无效时可设UA为PC)
恢复长按菜单
正则搜索
表格排序

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/cmd/index.html b/cmd/index.html index e69de29..ba00ce1 100644 --- a/cmd/index.html +++ b/cmd/index.html @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + 一键执行任意预定义命令(附手机PC剪贴板互通) + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 一键执行任意预定义命令(附手机PC剪贴板互通) +
+ + +
+

技巧等级:中级 PC剪贴板(高级)

+

uweb浏览器支持一键执行任意预定义命令,这些命令可以与剪贴板交互,可以将结果(文本、图像、音视频)输出到浏览器窗口。

+

手机推荐安装uweb定制Termux,否则能够执行的命令极其有限。

+

预定义命令保存在文件”/sdcard/uweb/default.cmds”中。重启浏览器,长按历史按钮,超微将弹出菜单供用户点击执行。

+

资深用户可能注意到文件名与default.acmd类似。default.acmd中的命令适合以不同的参数反复执行;而default.cmds一般以单次执行为多。default.acmd结果会显示在浏览器当前窗口;而default.cmds中命令执行结果会显示在新窗口之中。这两个文件格式也完全相同,每行格式如下:
[命令名称]:[mimetype]:[命令代码]

+

命令代码可以是任意命令,其中可以包含%c(当前网址cookie)、%s (地址栏输入)、 %t (当前窗口标题)、 %u (当前窗口url或文件路径)。执行时这些特殊标识将会被相应内容自动替换。

+

mimetype用来表示命令的输出类型。除了标准的mimetype之外,超微对此还作了扩充,便利与剪贴板交互。下面是扩充版的mimetype:
“clip/clip” : 以剪贴板作为命令输入,输出结果复制到剪贴板。
“/clip” : 输出结果复制到剪贴板。
“clip/text/html” : 以剪贴板作为命令输入,输出结果mimetype类型为“text/html”。
“termux/*”: 在termux中执行命令。

+

下面是笔者使用的default.cmds配置(命令具体解释):

+
复制手机剪贴板至PC剪贴板:clip:ssh [user:password]@192.168.2.102 "DISPLAY=:0 xsel -i"
+PC剪贴板至手机剪贴板:/clip:ssh [user:password]@192.168.2.102 "DISPLAY=:0 xsel -o"
+
+
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/css/aircloud.css b/css/aircloud.css index e69de29..2e177cf 100644 --- a/css/aircloud.css +++ b/css/aircloud.css @@ -0,0 +1,1146 @@ +/*varibles*/ +* { + font-family: "italic", Helvetica, Arial, "Heiti SC", "Microsoft YaHei"; +} +body, +html { + margin: 0; + padding: 0; +} +body { + margin-left: calc(100vw - 100%) !important; +} +.red { + color: red; +} +.hide { + display: none !important; +} +.show-block { + display: block !important; +} +.show-block { + animation: showBlock 0.4s forwards; + display: block !important; +} +@keyframes showBlock { + from { + opacity: 0; + transform: translateY(-100%); + } + to { + opacity: 1; + transform: translateY(0); + } +} +.hide-block { + display: block !important; + animation: hideBlock 0.4s forwards; + opacity: 1; + transform: translateY(0); +} +@keyframes hideBlock { + from { + opacity: 1; + transform: translateY(0); + } + to { + opacity: 0; + transform: translateY(-100%); + display: none; + } +} +.show-flex-fade { + animation: showFade 0.4s forwards; + display: flex !important; +} +.hide-flex-fade { + animation: hideFade 0.4s forwards; +} +@keyframes showFade { + from { + opacity: 0; + } + to { + opacity: 1; + } +} +@keyframes hideFade { + from { + opacity: 1; + } + to { + opacity: 0; + display: none !important; + } +} +.no-indent { + text-indent: 0 !important; +} +.no-indent p, +.no-indent h1, +.no-indent h2, +.no-indent h3, +.no-indent h4, +.no-indent h5, +.no-indent h6, +.no-indent ul, +.no-indent ol { + text-indent: 0 !important; +} +.nav { + position: relative; + padding-top: 50px; + color: #333333; + width: 100%; + display: flex; + flex-direction: column; + align-items: center; +} +.nav .avatar-name { + display: flex; + flex-direction: column; + align-items: center; + border-bottom: 1px solid #979797; +} +.nav .avatar-name .avatar { + width: 120px; + height: 120px; + padding: 10px; + box-sizing: border-box; +} +.nav .avatar-name .avatar img { + width: 100px; + height: 100px; +} +.nav .avatar-name .name { + margin-top: 10px; + margin-bottom: 20px; +} +.nav .avatar-name .name i { + font-size: 16px; + font-family: "italic" !important; + font-weight: 300; + color: #666666; +} +.nav .contents ul { + width: 100%; + padding-left: 0; + margin-top: 25px; + margin-bottom: 25px; +} +.nav .contents ul li, +.nav .contents ul li a { + text-decoration: none; + font-size: 15px; + margin: 20px auto; + padding-left: 0; + list-style: none; +} +.nav .contents ul li i, +.nav .contents ul li a i { + cursor: pointer; + color: #999999; + margin-right: 5px; +} +.nav .contents ul li span, +.nav .contents ul li a span { + cursor: pointer; + color: #999999; +} +.nav .contents ul li.active span, +.nav .contents ul li.active i { + color: #4a4a4a; +} +.nav .contents ul li:hover span, +.nav .contents ul li:hover i { + color: #4a4a4a; +} +.site-nav-toggle { + display: none; +} +.site-nav-toggle button { + outline: none; + margin-top: 2px; + padding: 9px 10px; + background: transparent; + border: none; + user-select: none; +} +.site-nav-toggle button .btn-bar { + display: block; + width: 22px; + height: 2px; + background: #666666; + border-radius: 1px; +} +.site-nav-toggle button .btn-bar + .btn-bar { + margin-top: 4px; +} +.search-field { + overflow: hidden; + display: none; + position: fixed; + top: 0; + bottom: 0; + z-index: 3; + left: 0; + right: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.3); + align-items: center; + flex-direction: column; +} +.search-field .search-container { + width: 40vw; + min-width: 500px; + height: 70vh; + margin-top: 15vh; +} +.search-field .search-container .search-input { + width: 100%; + display: flex; + align-items: center; + padding-top: 10px; +} +.search-field .search-container .search-input span { + width: 60px; + color: #999999; + line-height: 30px; + text-align: center; +} +.search-field .search-container .search-input span:nth-child(1) { + width: 40px; +} +.search-field .search-container .search-input #begin-search { + cursor: pointer; +} +.search-field .search-container .search-input #begin-search:hover { + color: #4a4a4a; +} +.search-field .search-container .search-input input { + flex: 1; + background-color: #f3f4f7; + border: 1px solid #cccccc; + height: 30px; + font-size: 18px; + color: #4a4a4a; + box-sizing: border-box; + font-weight: 300; + padding-left: 5px; + padding-right: 5px; +} +.search-field .search-result-container { + height: calc(70vh - 50px); + overflow-y: scroll; + overflow-x: hidden; +} +.search-field .search-result-container::-webkit-scrollbar { + width: 4px; +} +.search-field .search-result-container .no-search-result { + width: 100%; + height: 200px; + text-align: center; + padding-top: 100px; + color: #999999; + font-size: 16px; +} +.search-field .search-result-container::-webkit-scrollbar-thumb { + background-color: #c3c4c7; + -webkit-border-radius: 2px; + border-radius: 2px; +} +.search-field .search-result-container ul { + margin-top: 10px; + width: calc(100% - 25px); + padding-left: 10px; +} +.search-field .search-result-container ul li { + margin-bottom: 15px; + list-style: none; +} +.search-field .search-result-container ul li a { + text-decoration: none; + cursor: pointer; + font-size: 16px; + color: #4a4a4a; + font-weight: 300; + padding-bottom: 5px; +} +.search-field .search-result-container ul li ul { + padding-left: 10px; +} +.search-field .search-result-container ul li ul li { + list-style: none; + color: #666666; + font-weight: 300; + font-size: 13px; +} +@media screen and (max-width: 680px) { + .search-field .search-container { + min-width: 0; + width: 100%; + height: 100%; + margin: 0; + } + .search-field .search-result-container { + height: calc(100vh - 50px); + } + .nav { + margin-top: 50px; + position: relative; + top: 0; + width: 100%; + } + .nav .avatar-name { + border-bottom: none; + } + .nav .contents { + display: none; + position: fixed; + left: 0; + top: 40px; + width: 100%; + border-bottom: 1px solid #CCCCCC; + border-top: 1px solid #CCCCCC; + } + .nav .contents ul { + padding-left: 30px; + } + .site-nav-toggle { + height: 40px; + box-sizing: border-box; + display: block; + position: fixed; + width: 100%; + padding-top: 2px; + padding-left: 20px; + z-index: 2; + } +} +.post-preview { + width: 100%; + height: max-content; + margin-bottom: 10px; + box-sizing: border-box; + display: flex; + flex-direction: row; +} +.post-preview .post-time { + font-size: 17px; + color: #999999; + width: 125px; + font-weight: 300; + line-height: 24px; +} +.post-preview .post-info { + flex: 1; +} +.post-preview .post-info a { + cursor: pointer; + text-decoration: none; +} +.post-preview .post-info a h3 { + line-height: 24px; + cursor: pointer; + margin-top: 0; + margin-bottom: 5px; + color: #101010; + font-size: 18px; + font-weight: 300; + transition: color 0.4s; +} +.post-preview .post-info a h3:hover { + color: #4990E2; +} +.post-preview .post-info p { + margin-top: 0; +} +.post-preview .post-info p span, +.post-preview .post-info p a { + font-weight: 300; + color: #999999; + font-size: 14px; + text-decoration: none; +} +.post-preview-container { + min-height: 420px; +} +.pager { + width: 100%; + height: 40px; + padding-left: 0; + display: flex; +} +.pager .previous { + flex: 1; + display: flex; + flex-direction: row; + cursor: pointer; +} +.pager .next { + flex: 1; + display: flex; + flex-direction: row-reverse; + cursor: pointer; +} +.pager .previous a, +.pager .next a { + box-sizing: border-box; + cursor: pointer; + transition: color 0.4s, background-color 0.4s; + border: 1px solid #999999; + line-height: 40px; + width: 150px; + height: 40px; + font-size: 18px; + color: #999999; + text-align: center; + text-decoration: none; +} +.pager .previous a:hover, +.pager .next a:hover { + color: white; + cursor: pointer; + background-color: #666666; +} +@media screen and (max-width: 680px) { + .post-preview-container { + min-height: 0 !important; + } + .post-preview { + width: 100%; + height: max-content; + margin-bottom: 10px; + box-sizing: border-box; + display: flex; + flex-direction: column; + padding-left: 10px; + padding-right: 10px; + border-bottom: 1px solid #EEEEEE; + } + .post-preview .post-time { + font-size: 11px; + color: #999999; + width: 125px; + font-weight: 300; + line-height: 20px; + font-style: oblique; + } + .post-preview .post-info { + flex: 1; + } + .post-preview .post-info a { + cursor: pointer; + text-decoration: none; + } + .post-preview .post-info a h3 { + line-height: 20px; + cursor: pointer; + margin-top: 0; + margin-bottom: 5px; + color: #101010; + font-size: 15px; + font-weight: 300; + } + .post-preview .post-info p { + margin-top: 0; + } + .post-preview .post-info p span, + .post-preview .post-info p a { + font-weight: 300; + color: #999999; + font-size: 12px; + text-decoration: none; + } + .pager { + width: 100%; + height: 40px; + padding-left: 10px; + padding-right: 10px; + display: flex; + } + .pager .previous { + flex: 1; + display: flex; + flex-direction: row; + cursor: pointer; + } + .pager .next { + flex: 1; + display: flex; + flex-direction: row-reverse; + cursor: pointer; + } + .pager .previous a, + .pager .next a { + box-sizing: border-box; + cursor: pointer; + transition: color 0.4s, background-color 0.4s; + border: 1px solid #999999; + line-height: 30px; + width: 120px; + height: 30px; + font-size: 14px; + color: #999999; + text-align: center; + text-decoration: none; + } + .pager .previous a:hover, + .pager .next a:hover { + color: white; + cursor: pointer; + background-color: #666666; + } +} +.tags { + line-height: 30px; + margin-bottom: 25px; +} +.tags a { + text-decoration: none; + color: #999999; + margin-right: 15px; +} +.tags a:hover { + color: #4a4a4a; +} +.tags a::before { + content: "#"; +} +.one-tag-list { + margin-bottom: 25px; +} +.one-tag-list .fa-tag { + margin-bottom: 15px; + display: block; + color: #999999; +} +.one-tag-list .post-preview { + padding-left: 2em; +} +.one-tag-list .post-preview a { + cursor: pointer; + text-decoration: none; +} +.one-tag-list .post-preview a .post-title { + margin-bottom: 5px; + line-height: 20px; + cursor: pointer; + margin-top: 0; + color: #101010; + font-size: 18px; + font-weight: 300; + transition: color 0.4s; +} +.one-tag-list .post-preview a .post-title:hover { + color: #4990E2; +} +@media screen and (max-width: 680px) { + .one-tag-list { + margin-bottom: 25px; + } + .one-tag-list .fa-tag { + margin-bottom: 15px; + display: block; + color: #999999; + } + .one-tag-list .post-preview { + padding-left: 2em; + } + .one-tag-list .post-preview a { + cursor: pointer; + text-decoration: none; + } + .one-tag-list .post-preview a .post-title { + font-size: 14px; + font-weight: 300; + text-decoration: none; + line-height: 20px; + color: #4a4a4a; + margin-bottom: 5px; + cursor: pointer; + margin-top: 0; + transition: color 0.4s; + } + .one-tag-list .post-preview a .post-title:hover { + color: #4990E2; + } +} +.post-container { + width: 100%; + height: max-content; + display: flex; + flex-direction: column; +} +.post-container .post-title { + width: 100%; + text-align: center; + line-height: 24px; + margin-top: 0; + margin-bottom: 5px; + color: #101010; + font-size: 20px; + font-weight: 300; +} +.post-container .post-meta { + text-align: center; + margin-top: 0; + margin-bottom: 20px; +} +.post-container .post-meta span, +.post-container .post-meta a { + font-weight: 300; + color: #999999; + font-size: 13px; + text-decoration: none; +} +.post-container .post-meta .attr { + margin-right: 5px; + margin-left: 5px; +} +.post-content { + line-height: 20px; + font-size: 15px; + text-indent: 0; + color: #333333; + font-weight: 300; +} +.post-content blockquote { + border-top: 1px solid #cccccc; + border-bottom: 1px solid #cccccc; + margin-left: 2em; + margin-right: 2em; + padding-left: 0; + padding-right: 0; +} +.post-content blockquote p { + margin-top: 10px; + margin-bottom: 10px; + color: #666666; +} +.post-content a { + text-decoration: none; + color: #4990E2; +} +.post-content p { + color: #404040; + font-size: 14px; + line-height: 30px; + text-indent: 0; + letter-spacing: 1px; +} +.post-content p img { + width: 80%; +} +.post-content ul, +.post-content ol { + padding-left: 2em; +} +.post-content ul li, +.post-content ol li { + list-style: none; + color: #404040; + font-size: 14px; + line-height: 30px; + text-indent: 0; + letter-spacing: 1px; + margin-bottom: 5px; + margin-top: 5px; +} +.post-content ul li:before, +.post-content ol li:before { + content: '• '; +} +.post-content pre { + text-indent: 0; + padding: 10px; +} +.post-content pre code { + line-height: 175%; +} +.post-content h1 { + color: #333333; + margin-top: 20px; + margin-bottom: 20px; +} +.post-content h2 { + color: #333333; + margin-top: 20px; + margin-bottom: 20px; +} +.post-content h3 { + color: #333333; + margin-top: 20px; + margin-bottom: 20px; +} +.post-content h4 { + color: #333333; + margin-top: 20px; + margin-bottom: 20px; +} +.post-content h5 { + color: #333333; + margin-top: 20px; + margin-bottom: 20px; +} +.post-content h6 { + color: #333333; + margin-top: 20px; + margin-bottom: 20px; +} +#comment-container { + text-indent: 0; +} +#lv-container { + text-indent: 0; +} +.post-content li p { + display: inline; +} +.index-about { + text-align: center; + width: 100%; + margin-top: 45px; + margin-bottom: 40px; + opacity: 0; + animation: showBlock 1.6s forwards; +} +.index-about i { + font-size: 15px; + font-family: "italic" !important; + font-weight: 300; + color: #444444; +} +.index-about-mobile { + display: none; +} +.index-container { + justify-content: center; + height: max-content; + position: relative; + width: 1024px; + margin: auto; + display: flex; + flex-direction: row; +} +.index-container .index-left { + width: 240px; +} +.index-container .index-middle { + max-width: 784px; + flex: 1; +} +@media screen and (max-width: 1180px) { + .index-container { + left: 0; + width: 100%; + box-sizing: border-box; + margin: auto; + padding: 0 40px 0 10px; + display: flex; + flex-direction: row; + } + .index-container .index-left { + width: 180px; + } + .index-container .index-middle { + flex: 1; + max-width: calc(100% - 180px); + } +} +@media screen and (max-width: 680px) { + .index-container { + width: 100%; + box-sizing: border-box; + margin: auto; + display: flex; + flex-direction: column; + padding: 0 25px 0 25px; + min-height: 0; + } + .index-container .index-left { + width: 100%; + } + .index-container .index-middle { + max-width: 100%; + flex: 1; + } + .index-about { + display: none; + } + .index-about-mobile { + display: block; + text-align: center; + width: 100%; + margin-top: 0; + margin-bottom: 40px; + } + .index-about-mobile i { + font-size: 15px; + font-family: "italic" !important; + font-weight: 300; + color: #444444; + } +} +.archives-container .one-tag-list .listing-seperator { + font-size: 18px; + color: #999999; +} +.archives-container .one-tag-list ul { + list-style: none; +} +.archives-container .one-tag-list ul li { + display: flex; + align-items: center; + flex-direction: row; + margin-bottom: 10px; +} +.archives-container .one-tag-list ul li span { + color: #999999; + margin-right: 15px; + min-width: 45px; +} +.archives-container .one-tag-list ul li a { + text-decoration: none; + line-height: 20px; + color: #4a4a4a; +} +.archives-container .one-tag-list ul li a span { + color: #4a4a4a; + transition: color 0.4s; +} +.archives-container .one-tag-list ul li a span:hover { + color: #4990E2; +} +@media screen and (max-width: 680px) { + .archives-container .one-tag-list .listing-seperator { + font-size: 18px; + color: #999999; + } + .archives-container .one-tag-list ul { + list-style: none; + padding-left: 1em; + } + .archives-container .one-tag-list ul li { + display: flex; + align-items: center; + flex-direction: row; + margin-bottom: 10px; + } + .archives-container .one-tag-list ul li span { + color: #999999; + margin-right: 15px; + min-width: 45px; + font-size: 14px; + } + .archives-container .one-tag-list ul li i { + font-size: 12px; + } + .archives-container .one-tag-list ul li a { + font-size: 14px; + font-weight: 300; + text-decoration: none; + line-height: 20px; + color: #4a4a4a; + } + .archives-container .one-tag-list ul li a span { + color: #4a4a4a; + } +} +pre, +.highlight { + overflow: auto; + margin: 20px 0; + padding: 0; + font-size: 13px; + color: #4d4d4c; + background: #f7f7f7; + line-height: 1.6; +} +pre, +code { + font-family: consolas, Menlo, "PingFang SC", "Microsoft YaHei", monospace; +} +code { + padding: 2px 4px; + word-wrap: break-word; + color: #555; + background: #eee; + border-radius: 3px; + font-size: 13px; +} +pre { + padding: 10px; +} +pre code { + padding: 0; + color: #4d4d4c; + background: none; + text-shadow: none; +} +.highlight { + border-radius: 1px; +} +.highlight pre { + border: none; + margin: 0; + padding: 10px 0; +} +.highlight table { + margin: 0; + width: auto; + border: none; +} +.highlight td { + border: none; + padding: 0; +} +.highlight figcaption { + font-size: 1em; + color: #4d4d4c; + line-height: 1em; + margin-bottom: 1em; +} +.highlight figcaption a { + float: right; + color: #4d4d4c; +} +.highlight figcaption a:hover { + border-bottom-color: #4d4d4c; +} +.highlight .gutter pre { + padding-left: 10px; + padding-right: 10px; + color: #869194; + text-align: right; + background-color: #eff2f3; +} +.highlight .code pre { + width: 100%; + padding-left: 10px; + padding-right: 10px; + background-color: #f7f7f7; +} +.highlight .line { + height: 20px; +} +.gutter { + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.gist table { + width: auto; +} +.gist table td { + border: none; +} +pre .deletion { + background: #fdd; +} +pre .addition { + background: #dfd; +} +pre .meta { + color: #8959a8; +} +pre .comment { + color: #8e908c; +} +pre .variable, +pre .attribute, +pre .tag, +pre .regexp, +pre .ruby .constant, +pre .xml .tag .title, +pre .xml .pi, +pre .xml .doctype, +pre .html .doctype, +pre .css .id, +pre .css .class, +pre .css .pseudo { + color: #c82829; +} +pre .number, +pre .preprocessor, +pre .built_in, +pre .literal, +pre .params, +pre .constant, +pre .command { + color: #f5871f; +} +pre .ruby .class .title, +pre .css .rules .attribute, +pre .string, +pre .value, +pre .inheritance, +pre .header, +pre .ruby .symbol, +pre .xml .cdata, +pre .special, +pre .number, +pre .formula { + color: #718c00; +} +pre .title, +pre .css .hexcolor { + color: #3e999f; +} +pre .function, +pre .python .decorator, +pre .python .title, +pre .ruby .function .title, +pre .ruby .title .keyword, +pre .perl .sub, +pre .javascript .title, +pre .coffeescript .title { + color: #4271ae; +} +pre .keyword, +pre .javascript .function { + color: #8959a8; +} +.footer { + width: 100%; + align-items: center; + display: flex; + flex-direction: column; + color: #979797; + margin-bottom: 10px; +} +.footer p { + font-family: "Montserrat", "Helvetica Neue", "Hiragino Sans GB", "LiHei Pro", Arial, sans-serif; + font-size: 14px; + margin-top: 5px; + margin-bottom: 0; + font-weight: 300; +} +.footer p a { + font-weight: 300; + font-family: "Montserrat", "Helvetica Neue", "Hiragino Sans GB", "LiHei Pro", Arial, sans-serif; + cursor: pointer; + color: #333333; +} +.footer p span a { + font-weight: 300; + font-family: "Montserrat", "Helvetica Neue", "Hiragino Sans GB", "LiHei Pro", Arial, sans-serif; + cursor: pointer; + color: #979797; + text-decoration: none; +} +.footer p span a:hover { + color: #333333; +} +.list-inline.text-center { + color: #444444; + font-size: 20px; + padding-left: 0; + margin-bottom: 0; +} +.list-inline.text-center li { + display: inline-block; + margin: 0 2px; + background-color: #979797; + height: 24px; + width: 24px; + border-radius: 12px; + text-align: center; +} +.list-inline.text-center li a { + text-decoration: none; +} +.list-inline.text-center li a span i { + line-height: 20px; + color: white; +} +.list-inline.text-center li:hover { + background-color: #333333; +} +@media screen and (max-width: 680px) { + .footer { + box-sizing: border-box; + padding-left: 20px; + padding-right: 20px; + } + .footer p { + font-family: "Montserrat", "Helvetica Neue", "Hiragino Sans GB", "LiHei Pro", Arial, sans-serif; + font-size: 11px; + margin-top: 5px; + margin-bottom: 0; + font-weight: 300; + } + .footer p span a { + font-size: 11px; + font-weight: 300; + font-family: "Montserrat", "Helvetica Neue", "Hiragino Sans GB", "LiHei Pro", Arial, sans-serif; + cursor: pointer; + color: #979797; + text-decoration: none; + } + .footer p span a:hover { + color: #333333; + } +} +.toc-article { + width: 240px; +} +.toc-article ol { + padding-left: 10px; + cursor: pointer; + font-size: 0; +} +.toc-article li { + font-size: 0; + box-sizing: border-box; + border-left: 2px solid #cccccc; + list-style: none; + padding-left: 10px; +} +.toc-article li a { + display: block; + line-height: 20px; + margin-bottom: 10px; + text-decoration: none; + color: #999999; + font-size: 14px; +} +.toc-article li a span { + word-break: break-all; +} +.toc-article li.active { + border-left: 2px solid #4990E2; +} +.toc-article li.active > a { + color: #4990E2; +} +.toc-article li:hover { + border-left: 2px solid #4990E2; +} +.toc-article li:hover > a { + color: #4990E2; +} +.toc-article > ol > li { + border-left: none !important; +} +.toc-fixed { + position: fixed; + top: 10px; + width: 240px; +} +.toc-fixed::-webkit-scrollbar { + width: 0; +} +.toc-fixed::-webkit-scrollbar-thumb { + -webkit-border-radius: 4px; + border-radius: 2px; +} +@media screen and (max-width: 1180px) { + .toc-article { + display: none; + } +} diff --git a/css/aircloud.less b/css/aircloud.less index e69de29..58208cd 100644 --- a/css/aircloud.less +++ b/css/aircloud.less @@ -0,0 +1,19 @@ +@import "../_less/variables"; +@import "../_less/common"; +@import "../_less/nav"; +@import "../_less/about"; +@import "../_less/index"; +@import "../_less/tag"; +@import "../_less/post"; +@import "../_less/page"; +@import "../_less/layout"; + + +@import "../_less/archive"; + +@import "../_less/hightlight"; +// _partial: +@import "../_less/_partial/footer"; + +@import "../_less/toc"; + diff --git a/css/gitment.css b/css/gitment.css index e69de29..5414f78 100644 --- a/css/gitment.css +++ b/css/gitment.css @@ -0,0 +1,1146 @@ +.gitment-container { + font-family: sans-serif; + font-size: 14px; + line-height: 1.5; + color: #333; + word-wrap: break-word; +} + +.gitment-container * { + box-sizing: border-box; +} + +.gitment-container *:disabled { + cursor: not-allowed; +} + +.gitment-container a, +.gitment-container a:visited { + cursor: pointer; + text-decoration: none; +} + +.gitment-container a:hover { + text-decoration: underline; +} + +.gitment-container .gitment-hidden { + display: none; +} + +.gitment-container .gitment-spinner-icon { + fill: #333; + + -webkit-animation: gitment-spin 1s steps(12) infinite; + animation: gitment-spin 1s steps(12) infinite; +} + +@-webkit-keyframes gitment-spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +@keyframes gitment-spin { + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg) + } +} + +.gitment-root-container { + margin: 19px 0; +} + +.gitment-header-container { + margin: 19px 0; +} + +.gitment-header-like-btn, +.gitment-comment-like-btn { + cursor: pointer; +} + +.gitment-comment-like-btn { + float: right; +} + +.gitment-comment-like-btn.liked { + color: #F44336; +} + +.gitment-header-like-btn svg { + vertical-align: middle; + height: 30px; +} + +.gitment-comment-like-btn svg { + vertical-align: middle; + height: 20px; +} + +.gitment-header-like-btn.liked svg, +.gitment-comment-like-btn.liked svg { + fill: #F44336; +} + +a.gitment-header-issue-link, +a.gitment-header-issue-link:visited { + float: right; + line-height: 30px; + color: #666; +} + +a.gitment-header-issue-link:hover { + color: #666; +} + +.gitment-comments-loading, +.gitment-comments-error, +.gitment-comments-empty { + text-align: center; + margin: 50px 0; +} + +.gitment-comments-list { + list-style: none; + padding-left: 0; + margin: 0 0 38px; +} + +.gitment-comment, +.gitment-editor-container { + position: relative; + min-height: 60px; + padding-left: 60px; + margin: 19px 0; +} + +.gitment-comment-avatar, +.gitment-editor-avatar { + float: left; + margin-left: -60px; +} + +.gitment-comment-avatar, +.gitment-comment-avatar-img, +.gitment-comment-avatar, +.gitment-editor-avatar-img, +.gitment-editor-avatar svg { + width: 44px; + height: 44px; + border-radius: 3px; +} + +.gitment-editor-avatar .gitment-github-icon { + fill: #fff; + background-color: #333; +} + +.gitment-comment-main, +.gitment-editor-main { + position: relative; + border: 1px solid #CFD8DC; + border-radius: 0; +} + +.gitment-editor-main::before, +.gitment-editor-main::after, +.gitment-comment-main::before, +.gitment-comment-main::after { + position: absolute; + top: 11px; + left: -16px; + display: block; + width: 0; + height: 0; + pointer-events: none; + content: ""; + border-color: transparent; + border-style: solid solid outset; +} + +.gitment-editor-main::before, +.gitment-comment-main::before { + border-width: 8px; + border-right-color: #CFD8DC; +} + +.gitment-editor-main::after, +.gitment-comment-main::after { + margin-top: 1px; + margin-left: 2px; + border-width: 7px; + border-right-color: #fff; +} + +.gitment-comment-header { + margin: 12px 15px; + color: #666; + background-color: #fff; + border-radius: 3px; +} + +.gitment-editor-header { + padding: 0; + margin: 0; + border-bottom: 1px solid #CFD8DC; +} + +a.gitment-comment-name, +a.gitment-comment-name:visited { + font-weight: 600; + color: #666; +} + +.gitment-editor-tabs { + margin-bottom: -1px; + margin-left: -1px; +} + +.gitment-editor-tab { + display: inline-block; + padding: 11px 12px; + font-size: 14px; + line-height: 20px; + color: #666; + text-decoration: none; + background-color: transparent; + border-width: 0 1px; + border-style: solid; + border-color: transparent; + border-radius: 0; + + white-space: nowrap; + cursor: pointer; + user-select: none; + + outline: none; +} + +.gitment-editor-tab.gitment-selected { + color: #333; + background-color: #fff; + border-color: #CFD8DC; +} + +.gitment-editor-login { + float: right; + margin-top: -30px; + margin-right: 15px; +} + +a.gitment-footer-project-link, +a.gitment-footer-project-link:visited, +a.gitment-editor-login-link, +a.gitment-editor-login-link:visited { + color: #2196F3; +} + +a.gitment-editor-logout-link, +a.gitment-editor-logout-link:visited { + color: #666; +} + +a.gitment-editor-logout-link:hover { + color: #2196F3; + text-decoration: none; +} + +.gitment-comment-body { + position: relative; + margin: 12px 15px; + overflow: hidden; + border-radius: 3px; +} + +.gitment-comment-body-folded { + cursor: pointer; +} + +.gitment-comment-body-folded::before { + display: block !important; + content: ""; + position: absolute; + width: 100%; + left: 0; + top: 0; + bottom: 50px; + pointer-events: none; + background: -webkit-linear-gradient(top, rgba(255, 255, 255, 0), rgba(255, 255, 255, .9)); + background: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(255, 255, 255, .9)); +} + +.gitment-comment-body-folded::after { + display: block !important; + content: "Click to Expand" !important; + text-align: center; + color: #666; + position: absolute; + width: 100%; + height: 50px; + line-height: 50px; + left: 0; + bottom: 0; + pointer-events: none; + background: rgba(255, 255, 255, .9); +} + +.gitment-editor-body { + margin: 0; +} + +.gitment-comment-body > *:first-child, +.gitment-editor-preview > *:first-child { + margin-top: 0 !important; +} + +.gitment-comment-body > *:last-child, +.gitment-editor-preview > *:last-child { + margin-bottom: 0 !important; +} + +.gitment-editor-body textarea { + display: block; + width: 100%; + min-height: 150px; + max-height: 500px; + padding: 16px; + resize: vertical; + + max-width: 100%; + margin: 0; + font-size: 14px; + line-height: 1.6; + + background-color: #fff; + + color: #333; + vertical-align: middle; + border: none; + border-radius: 0; + outline: none; + box-shadow: none; + + overflow: visible; +} + +.gitment-editor-body textarea:focus { + background-color: #fff; +} + +.gitment-editor-preview { + min-height: 150px; + + padding: 16px; + background-color: transparent; + + width: 100%; + font-size: 14px; + + line-height: 1.5; + word-wrap: break-word; +} + +.gitment-editor-footer { + padding: 0; + margin-top: 10px; +} + +.gitment-editor-footer::after { + display: table; + clear: both; + content: ""; +} + +a.gitment-editor-footer-tip { + display: inline-block; + padding-top: 10px; + font-size: 12px; + color: #666; +} + +a.gitment-editor-footer-tip:hover { + color: #2196F3; + text-decoration: none; +} + +.gitment-comments-pagination { + list-style: none; + text-align: right; + border-radius: 0; + margin: -19px 0 19px 0; +} + +.gitment-comments-page-item { + display: inline-block; + cursor: pointer; + border: 1px solid #CFD8DC; + margin-left: -1px; + padding: .25rem .5rem; +} + +.gitment-comments-page-item:hover { + background-color: #f5f5f5; +} + +.gitment-comments-page-item.gitment-selected { + background-color: #f5f5f5; +} + +.gitment-editor-submit, +.gitment-comments-init-btn { + color: #fff; + background-color: #00BCD4; + + position: relative; + display: inline-block; + padding: 7px 13px; + font-size: 14px; + font-weight: 600; + line-height: 20px; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-size: 110% 110%; + border: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.gitment-editor-submit:hover, +.gitment-comments-init-btn:hover { + background-color: #00ACC1; +} + +.gitment-comments-init-btn:disabled, +.gitment-editor-submit:disabled { + color: rgba(255,255,255,0.75); + background-color: #4DD0E1; + box-shadow: none; +} + +.gitment-editor-submit { + float: right; +} + +.gitment-footer-container { + margin-top: 30px; + margin-bottom: 20px; + text-align: right; + font-size: 12px; +} + +/* + * Markdown CSS + * Copied from https://github.com/sindresorhus/github-markdown-css + */ +.gitment-markdown { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; + line-height: 1.5; + color: #333; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + font-size: 16px; + line-height: 1.5; + word-wrap: break-word; +} + +.gitment-markdown .pl-c { + color: #969896; +} + +.gitment-markdown .pl-c1, +.gitment-markdown .pl-s .pl-v { + color: #0086b3; +} + +.gitment-markdown .pl-e, +.gitment-markdown .pl-en { + color: #795da3; +} + +.gitment-markdown .pl-smi, +.gitment-markdown .pl-s .pl-s1 { + color: #333; +} + +.gitment-markdown .pl-ent { + color: #63a35c; +} + +.gitment-markdown .pl-k { + color: #a71d5d; +} + +.gitment-markdown .pl-s, +.gitment-markdown .pl-pds, +.gitment-markdown .pl-s .pl-pse .pl-s1, +.gitment-markdown .pl-sr, +.gitment-markdown .pl-sr .pl-cce, +.gitment-markdown .pl-sr .pl-sre, +.gitment-markdown .pl-sr .pl-sra { + color: #183691; +} + +.gitment-markdown .pl-v, +.gitment-markdown .pl-smw { + color: #ed6a43; +} + +.gitment-markdown .pl-bu { + color: #b52a1d; +} + +.gitment-markdown .pl-ii { + color: #f8f8f8; + background-color: #b52a1d; +} + +.gitment-markdown .pl-c2 { + color: #f8f8f8; + background-color: #b52a1d; +} + +.gitment-markdown .pl-c2::before { + content: "^M"; +} + +.gitment-markdown .pl-sr .pl-cce { + font-weight: bold; + color: #63a35c; +} + +.gitment-markdown .pl-ml { + color: #693a17; +} + +.gitment-markdown .pl-mh, +.gitment-markdown .pl-mh .pl-en, +.gitment-markdown .pl-ms { + font-weight: bold; + color: #1d3e81; +} + +.gitment-markdown .pl-mq { + color: #008080; +} + +.gitment-markdown .pl-mi { + font-style: italic; + color: #333; +} + +.gitment-markdown .pl-mb { + font-weight: bold; + color: #333; +} + +.gitment-markdown .pl-md { + color: #bd2c00; + background-color: #ffecec; +} + +.gitment-markdown .pl-mi1 { + color: #55a532; + background-color: #eaffea; +} + +.gitment-markdown .pl-mc { + color: #ef9700; + background-color: #ffe3b4; +} + +.gitment-markdown .pl-mi2 { + color: #d8d8d8; + background-color: #808080; +} + +.gitment-markdown .pl-mdr { + font-weight: bold; + color: #795da3; +} + +.gitment-markdown .pl-mo { + color: #1d3e81; +} + +.gitment-markdown .pl-ba { + color: #595e62; +} + +.gitment-markdown .pl-sg { + color: #c0c0c0; +} + +.gitment-markdown .pl-corl { + text-decoration: underline; + color: #183691; +} + +.gitment-markdown .octicon { + display: inline-block; + vertical-align: text-top; + fill: currentColor; +} + +.gitment-markdown a { + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +.gitment-markdown a:active, +.gitment-markdown a:hover { + outline-width: 0; +} + +.gitment-markdown strong { + font-weight: inherit; +} + +.gitment-markdown strong { + font-weight: bolder; +} + +.gitment-markdown h1 { + font-size: 2em; + margin: 0.67em 0; +} + +.gitment-markdown img { + border-style: none; +} + +.gitment-markdown svg:not(:root) { + overflow: hidden; +} + +.gitment-markdown code, +.gitment-markdown kbd, +.gitment-markdown pre { + font-family: monospace, monospace; + font-size: 1em; +} + +.gitment-markdown hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +.gitment-markdown input { + font: inherit; + margin: 0; +} + +.gitment-markdown input { + overflow: visible; +} + +.gitment-markdown [type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +.gitment-markdown * { + box-sizing: border-box; +} + +.gitment-markdown input { + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +.gitment-markdown a { + color: #0366d6; + text-decoration: none; +} + +.gitment-markdown a:hover { + text-decoration: underline; +} + +.gitment-markdown strong { + font-weight: 600; +} + +.gitment-markdown hr { + height: 0; + margin: 15px 0; + overflow: hidden; + background: transparent; + border: 0; + border-bottom: 1px solid #dfe2e5; +} + +.gitment-markdown hr::before { + display: table; + content: ""; +} + +.gitment-markdown hr::after { + display: table; + clear: both; + content: ""; +} + +.gitment-markdown table { + border-spacing: 0; + border-collapse: collapse; +} + +.gitment-markdown td, +.gitment-markdown th { + padding: 0; +} + +.gitment-markdown h1, +.gitment-markdown h2, +.gitment-markdown h3, +.gitment-markdown h4, +.gitment-markdown h5, +.gitment-markdown h6 { + margin-top: 0; + margin-bottom: 0; +} + +.gitment-markdown h1 { + font-size: 32px; + font-weight: 600; +} + +.gitment-markdown h2 { + font-size: 24px; + font-weight: 600; +} + +.gitment-markdown h3 { + font-size: 20px; + font-weight: 600; +} + +.gitment-markdown h4 { + font-size: 16px; + font-weight: 600; +} + +.gitment-markdown h5 { + font-size: 14px; + font-weight: 600; +} + +.gitment-markdown h6 { + font-size: 12px; + font-weight: 600; +} + +.gitment-markdown p { + margin-top: 0; + margin-bottom: 10px; +} + +.gitment-markdown blockquote { + margin: 0; +} + +.gitment-markdown ul, +.gitment-markdown ol { + padding-left: 0; + margin-top: 0; + margin-bottom: 0; +} + +.gitment-markdown ol ol, +.gitment-markdown ul ol { + list-style-type: lower-roman; +} + +.gitment-markdown ul ul ol, +.gitment-markdown ul ol ol, +.gitment-markdown ol ul ol, +.gitment-markdown ol ol ol { + list-style-type: lower-alpha; +} + +.gitment-markdown dd { + margin-left: 0; +} + +.gitment-markdown code { + font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + font-size: 12px; +} + +.gitment-markdown pre { + margin-top: 0; + margin-bottom: 0; + font: 12px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; +} + +.gitment-markdown .octicon { + vertical-align: text-bottom; +} + +.gitment-markdown .pl-0 { + padding-left: 0 !important; +} + +.gitment-markdown .pl-1 { + padding-left: 4px !important; +} + +.gitment-markdown .pl-2 { + padding-left: 8px !important; +} + +.gitment-markdown .pl-3 { + padding-left: 16px !important; +} + +.gitment-markdown .pl-4 { + padding-left: 24px !important; +} + +.gitment-markdown .pl-5 { + padding-left: 32px !important; +} + +.gitment-markdown .pl-6 { + padding-left: 40px !important; +} + +.gitment-markdown::before { + display: table; + content: ""; +} + +.gitment-markdown::after { + display: table; + clear: both; + content: ""; +} + +.gitment-markdown>*:first-child { + margin-top: 0 !important; +} + +.gitment-markdown>*:last-child { + margin-bottom: 0 !important; +} + +.gitment-markdown a:not([href]) { + color: inherit; + text-decoration: none; +} + +.gitment-markdown .anchor { + float: left; + padding-right: 4px; + margin-left: -20px; + line-height: 1; +} + +.gitment-markdown .anchor:focus { + outline: none; +} + +.gitment-markdown p, +.gitment-markdown blockquote, +.gitment-markdown ul, +.gitment-markdown ol, +.gitment-markdown dl, +.gitment-markdown table, +.gitment-markdown pre { + margin-top: 0; + margin-bottom: 16px; +} + +.gitment-markdown hr { + height: 0.25em; + padding: 0; + margin: 24px 0; + background-color: #e1e4e8; + border: 0; +} + +.gitment-markdown blockquote { + padding: 0 1em; + color: #6a737d; + border-left: 0.25em solid #dfe2e5; +} + +.gitment-markdown blockquote>:first-child { + margin-top: 0; +} + +.gitment-markdown blockquote>:last-child { + margin-bottom: 0; +} + +.gitment-markdown kbd { + display: inline-block; + padding: 3px 5px; + font-size: 11px; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fafbfc; + border: solid 1px #c6cbd1; + border-bottom-color: #959da5; + border-radius: 0; + box-shadow: inset 0 -1px 0 #959da5; +} + +.gitment-markdown h1, +.gitment-markdown h2, +.gitment-markdown h3, +.gitment-markdown h4, +.gitment-markdown h5, +.gitment-markdown h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; +} + +.gitment-markdown h1 .octicon-link, +.gitment-markdown h2 .octicon-link, +.gitment-markdown h3 .octicon-link, +.gitment-markdown h4 .octicon-link, +.gitment-markdown h5 .octicon-link, +.gitment-markdown h6 .octicon-link { + color: #1b1f23; + vertical-align: middle; + visibility: hidden; +} + +.gitment-markdown h1:hover .anchor, +.gitment-markdown h2:hover .anchor, +.gitment-markdown h3:hover .anchor, +.gitment-markdown h4:hover .anchor, +.gitment-markdown h5:hover .anchor, +.gitment-markdown h6:hover .anchor { + text-decoration: none; +} + +.gitment-markdown h1:hover .anchor .octicon-link, +.gitment-markdown h2:hover .anchor .octicon-link, +.gitment-markdown h3:hover .anchor .octicon-link, +.gitment-markdown h4:hover .anchor .octicon-link, +.gitment-markdown h5:hover .anchor .octicon-link, +.gitment-markdown h6:hover .anchor .octicon-link { + visibility: visible; +} + +.gitment-markdown h1 { + padding-bottom: 0.3em; + font-size: 2em; + border-bottom: 1px solid #eaecef; +} + +.gitment-markdown h2 { + padding-bottom: 0.3em; + font-size: 1.5em; + border-bottom: 1px solid #eaecef; +} + +.gitment-markdown h3 { + font-size: 1.25em; +} + +.gitment-markdown h4 { + font-size: 1em; +} + +.gitment-markdown h5 { + font-size: 0.875em; +} + +.gitment-markdown h6 { + font-size: 0.85em; + color: #6a737d; +} + +.gitment-markdown ul, +.gitment-markdown ol { + padding-left: 2em; +} + +.gitment-markdown ul ul, +.gitment-markdown ul ol, +.gitment-markdown ol ol, +.gitment-markdown ol ul { + margin-top: 0; + margin-bottom: 0; +} + +.gitment-markdown li>p { + margin-top: 16px; +} + +.gitment-markdown li+li { + margin-top: 0.25em; +} + +.gitment-markdown dl { + padding: 0; +} + +.gitment-markdown dl dt { + padding: 0; + margin-top: 16px; + font-size: 1em; + font-style: italic; + font-weight: 600; +} + +.gitment-markdown dl dd { + padding: 0 16px; + margin-bottom: 16px; +} + +.gitment-markdown table { + display: block; + width: 100%; + overflow: auto; +} + +.gitment-markdown table th { + font-weight: 600; +} + +.gitment-markdown table th, +.gitment-markdown table td { + padding: 6px 13px; + border: 1px solid #dfe2e5; +} + +.gitment-markdown table tr { + background-color: #fff; + border-top: 1px solid #c6cbd1; +} + +.gitment-markdown table tr:nth-child(2n) { + background-color: #f5f5f5; +} + +.gitment-markdown img { + max-width: 100%; + box-sizing: content-box; + background-color: #fff; +} + +.gitment-markdown code { + padding: 0; + padding-top: 0.2em; + padding-bottom: 0.2em; + margin: 0; + font-size: 85%; + background-color: rgba(27,31,35,0.05); + border-radius: 0; +} + +.gitment-markdown code::before, +.gitment-markdown code::after { + letter-spacing: -0.2em; + content: "\00a0"; +} + +.gitment-markdown pre { + word-wrap: normal; +} + +.gitment-markdown pre>code { + padding: 0; + margin: 0; + font-size: 100%; + word-break: normal; + white-space: pre; + background: transparent; + border: 0; +} + +.gitment-markdown .highlight { + margin-bottom: 16px; +} + +.gitment-markdown .highlight pre { + margin-bottom: 0; + word-break: normal; +} + +.gitment-markdown .highlight pre, +.gitment-markdown pre { + padding: 16px; + overflow: auto; + font-size: 85%; + line-height: 1.45; + background-color: #f5f5f5; + border-radius: 0; +} + +.gitment-markdown pre code { + display: inline; + max-width: auto; + padding: 0; + margin: 0; + overflow: visible; + line-height: inherit; + word-wrap: normal; + background-color: transparent; + border: 0; +} + +.gitment-markdown pre code::before, +.gitment-markdown pre code::after { + content: normal; +} + +.gitment-markdown .full-commit .btn-outline:not(:disabled):hover { + color: #005cc5; + border-color: #005cc5; +} + +.gitment-markdown kbd { + display: inline-block; + padding: 3px 5px; + font: 11px "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace; + line-height: 10px; + color: #444d56; + vertical-align: middle; + background-color: #fcfcfc; + border: solid 1px #c6cbd1; + border-bottom-color: #959da5; + border-radius: 0; + box-shadow: inset 0 -1px 0 #959da5; +} + +.gitment-markdown :checked+.radio-label { + position: relative; + z-index: 1; + border-color: #0366d6; +} + +.gitment-markdown .task-list-item { + list-style-type: none; +} + +.gitment-markdown .task-list-item+.task-list-item { + margin-top: 3px; +} + +.gitment-markdown .task-list-item input { + margin: 0 0.2em 0.25em -1.6em; + vertical-align: middle; +} + +.gitment-markdown hr { + border-bottom-color: #eee; +} \ No newline at end of file diff --git a/filecap/index.html b/filecap/index.html index e69de29..bdf245a 100644 --- a/filecap/index.html +++ b/filecap/index.html @@ -0,0 +1,196 @@ + + + + + + + + + + + + + + 利用文件预处理预览/查看/播放一切可下载资源 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用文件预处理预览/查看/播放一切可下载资源 +
+ + +
+

技巧等级:中级

+

文件预处理配置文件为/sdcard/uweb/default.filecap,每行格式如下:
[文件后缀]:[mimetype]:[处理命令]

+

其中文件后缀可允许最多两段后缀,譬如”txt.xz”,”html.gz”。
mimetype表示命令处理后的输出内容格式。
处理命令与default.cmds相同,主要可能用到如下替换:
%u(网址或文件路径)、%U(编码以后的网址)、%c(当前网址cookie)、%p(密码保护网站中的密码,curl格式)。

+

利用文件预处理,超微浏览器现在可以预览/查看/播放一切可下载资源,并且可以利用不同网站在线服务预览不同的文件,而手机上一个应用都不用装。

+

配置/sdcard/uweb/default.filecap如下:

+
txt:text/html:curl %p "%u"
+mp3:text/html:echo '<audio controls width=100% height=100%><source src="%u"></audio>'
+m4b:text/html:echo '<audio controls width=100% height=100%><source src="%u"></audio>'
+m3u8:text/html:echo '<video controls width=100% height=100%><source src="%u"></video>'
+mp4:text/html:echo '<video controls width=100% height=100%><source src="%u"></video>'
+mkv:text/html:echo '<video controls width=100% height=100%><source src="%u"></video>'
+doc::am start --user 0 -a android.intent.action.VIEW -d 'https://view.officeapps.live.com/op/view.aspx?src=%U'
+xls::am start --user 0 -a android.intent.action.VIEW -d 'https://view.officeapps.live.com/op/view.aspx?src=%U'
+ppt::am start --user 0 -a android.intent.action.VIEW -d 'https://view.officeapps.live.com/op/view.aspx?src=%U'
+docx::am start --user 0 -a android.intent.action.VIEW -d 'https://view.officeapps.live.com/op/view.aspx?src=%U'
+xlsx::am start --user 0 -a android.intent.action.VIEW -d 'https://view.officeapps.live.com/op/view.aspx?src=%U'
+pptx::am start --user 0 -a android.intent.action.VIEW -d 'https://view.officeapps.live.com/op/view.aspx?src=%U'
+xz:text/plain:curl %p "%u"|xz -d --
+ +

长按窗口按钮,勾选“文件预处理”,重启浏览器。则点击下载按钮时上述文件类型会自动预览。

+

如果用户配置中处理命令用到curl,则需要安装Termux,并在Termux中安装curl (“apt install curl”)。
如果用户不安装Termux,则上述配置命令中的”am”需要全部路径,需用”/system/bin/am”替换。

+

以上配置使用了微软服务预览office文档,微软服务必需当前UA为PC,否则会出现空白页面。有条件的用户建议使用google docs (“http://docs.google.com/gview?embedded=true&url=") 服务替换。

+

若使用手机应用预览文件,则docx处理命令可改为:

+
am start --user 0 -a android.intent.action.VIEW -d "%u" -t "application/docx"
+ +

其余常见文件的类型名:
application/msword
application/msexcel
application/pdf

+

目前已知服务:
google docs, 功能强大,可查看几乎一切文档,但 “我的所爱在山腰,想要得到山太高。”

+

微软office, 可预览office文档,ua必须是pc。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/filenames/index.html b/filenames/index.html index e69de29..376ed81 100644 --- a/filenames/index.html +++ b/filenames/index.html @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + 超微浏览器配置文件列表 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 超微浏览器配置文件列表 +
+ + +
+

下面列表中以”/“结尾者为目录,其余为文件。如果用户勾选“使用内部目录配置”,”sitejs/“,”sitecache/“等位于应用内部保护目录下。否则以下所有文件/目录均位于”/sdcard/uweb”:
“css/“:全局样式目录
“js/“: 全局脚本目录
“sitejs/“:类油猴脚本,针对特定网址
“sitecss/“:针对特定网址css样式
“bookmarklet/“:js脚本目录
“offline/“:
“sbookmark/“:超级书签默认目录
“sitecache/“:用户供应网站离线数据
“longclick/“:长按链接菜单(js)
“default.longclick”:长按链接菜单
“default.uas”:浏览器标识
“default.urls”:特色服务
“default.acmd”:浏览器地址栏功能配置
“default.hosts”:广告屏蔽文件
“default.redirect”:重定向配置
“default.select”:长按“书签”按钮配置
“default.cmds”:长按“历史”按钮配置
“default.links”:长按“链接”按钮配置
“default.filecap”:
“default.rjs”:远程及简单脚本
“default.siteconf”:网站独立设置
“default.autoc”:地址栏autocomplete候选字符串
“query.autoc”:主屏搜索autocomplete候选字符串
“home5.html”:自定义主屏
“home5.search”:主屏搜索引擎
“bookmark.html”:主书签
“quickstart.html”:快速访问
“colors.txt”:护眼背景色
“default.css”:勾选网址特定样式后无匹配情形下的默认样式
“night.css”:夜间模式,代替超微内部实现
“types.sniff”:嗅探类型
“sniff.log”:嗅探结果
“history.log”:访问历史
“query.log”:查询历史

+

应用内部保护目录(/data/data/info.torapp.uweb/files/):
“shortcut/“:动态shortcut刷新目录,若不存在则默认为”/sdcard/uweb/bookmark”目录。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/globalcss/index.html b/globalcss/index.html index e69de29..077da2b 100644 --- a/globalcss/index.html +++ b/globalcss/index.html @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + CSS样式 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ CSS样式 +
+ + +
+

超微浏览器自动装载”/sdcard/uweb/css”目录下所有.css文件作为全局样式供用户选用。点击以下配置链接可自动添加为全局样式:

+

配合透明状态栏(沉浸)

+

文件”/sdcard/uweb/night.css”为用户自定义夜间模式样式,点击以下配置链接安装不同的夜间模式:
webview 81+ 夜间模式

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/gnuplot/index.html b/gnuplot/index.html index e69de29..de4a5ec 100644 --- a/gnuplot/index.html +++ b/gnuplot/index.html @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + 利用浏览器地址栏对函数作图 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用浏览器地址栏对函数作图 +
+ + +
+

使用Android端uweb浏览器
Termux提供了方便的软件包管理系统,缺省的uWeb地址栏功能配置需用到作图软件gnuplot。

+

安装gnuplot

+ +

地址栏功能配置:

    +
  • 配置文件<a href=e:/sdcard/uweb/default.acmd>/sdcard/uweb/default.acmd每行格式如下:
    菜单名:mimeType:命令行
  • +
  • 命令行可包含参数%s,运行时自动用地址栏输入内容替换。
  • +
  • 如果浏览器窗口当前地址为本地url,则此目录同时作为命令行工作目录。
  • +
+

配置文件/sdcard/uweb/default.acmd如下:

命令:text/plain:%s
+函数作图:image/svg+xml:gnuplot -e 'set term svg;set output; plot %s'
+函数作图(3d):image/svg+xml:gnuplot -e 'set term svg;set output; splot %s'
+超级计算器:text/html:echo "%s"|bc -l -q
+

长按uweb浏览器底部工具条刷新按钮弹出地址栏功能选择,选择“函数作图”,地址栏内输入函数如sin(x)**5就可显示函数图案。

+

常见问题及诊断

    +
  • 确保gnuplot正确安装,在Termux提示符下,敲入gnuplot,然后回车,保证出现”gnuplot>”。
  • +
  • 确保gnuplot正常运行, 在Termux提示符下,执行下面命令:
    gnuplot -e 'set term svg;set output; plot x'
    屏幕输出应该为正常的svg文件(类似html文本)。
  • +
  • Termux应为uweb定制包,否则有一堆设定需要修改。
  • +
  • 超微浏览器下长按设置按钮,勾选“标准错误输出”。再次在地址栏执行画图操作,此时浏览器会显示出错信息。
  • +
  • 为保证地址栏输入函数符合gnuplot规范,首个测试函数建议为”x”,即整个地址栏内输入为”x”。
  • +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/hosts/index.html b/hosts/index.html index e69de29..338cd16 100644 --- a/hosts/index.html +++ b/hosts/index.html @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + 利用超级hosts文件加速访问国外网站 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用超级hosts文件加速访问国外网站 +
+ + +
+

不少国外网站本身虽可访问,但由于网站需要下载google,
facebook等屏蔽网址的资源而导致无法访问。超级hosts文件可屏蔽文件中域名的一切子域名、孙域名、……,从而主动屏蔽这些网址,最终允许浏览器快速访问合法网站。

+

使用Android端uweb浏览器
/sdcard/uweb/default.hosts内容如下:
googleadservices.com
googlesyndication.com
adsense.com
google.com
google-analytics.com
googletagservices.com
twitter.com
facebook.com
fbcdn.net

+

其它国外网址访问技巧:

+
    +
  • 尝试关闭javascript, 譬如程序员网站stackoverflow.com在关闭javascript的情况下国内一般均可快速访问。
  • +
  • 关闭网页图片
  • +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + diff --git a/index.html b/index.html index e69de29..3428a00 100644 --- a/index.html +++ b/index.html @@ -0,0 +1,490 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + +
+
+
2020-01-01
+ +
+
+
2019-04-01
+ +
+
+
2019-07-23
+ +
+
+
2020-01-10
+ +
+
+
2020-01-10
+ +
+
+
2020-03-10
+ +
+
+
2020-01-10
+ +
+
+
2020-01-10
+ +
+
+
2020-03-01
+ +
+
+
2019-07-01
+ +
+ + +
+
2020-04-18
+ +
+ +
+
2020-04-12
+ +
+ +
+
2020-04-08
+ +
+ +
+
2020-04-05
+ +
+ +
+
2020-03-30
+ +
+ +
+
2020-01-11
+ +
+ +
+
2020-01-11
+ +
+ +
+
2019-11-13
+ +
+ +
+
2019-11-12
+ +
+ +
+
2019-11-10
+ +
+ +
+
2019-06-07
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-06-05
+ +
+ +
+
2019-10-20
+ +
+
+ + +
+
+ + + + + + + + + + + + + + + + diff --git a/js/gitment.js b/js/gitment.js index e69de29..ef8778b 100644 --- a/js/gitment.js +++ b/js/gitment.js @@ -0,0 +1,3757 @@ +/** + * Created by Xiaotao.Nie on 11/04/2018. + * All right reserved + * IF you have any question please email onlythen@yeah.net + */ + +var Gitment = + /******/ (function(modules) { // webpackBootstrap + /******/ // The module cache + /******/ var installedModules = {}; + /******/ + /******/ // The require function + /******/ function __webpack_require__(moduleId) { + /******/ + /******/ // Check if module is in cache + /******/ if(installedModules[moduleId]) + /******/ return installedModules[moduleId].exports; + /******/ + /******/ // Create a new module (and put it into the cache) + /******/ var module = installedModules[moduleId] = { + /******/ i: moduleId, + /******/ l: false, + /******/ exports: {} + /******/ }; + /******/ + /******/ // Execute the module function + /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + /******/ + /******/ // Flag the module as loaded + /******/ module.l = true; + /******/ + /******/ // Return the exports of the module + /******/ return module.exports; + /******/ } + /******/ + /******/ + /******/ // expose the modules object (__webpack_modules__) + /******/ __webpack_require__.m = modules; + /******/ + /******/ // expose the module cache + /******/ __webpack_require__.c = installedModules; + /******/ + /******/ // identity function for calling harmony imports with the correct context + /******/ __webpack_require__.i = function(value) { return value; }; + /******/ + /******/ // define getter function for harmony exports + /******/ __webpack_require__.d = function(exports, name, getter) { + /******/ if(!__webpack_require__.o(exports, name)) { + /******/ Object.defineProperty(exports, name, { + /******/ configurable: false, + /******/ enumerable: true, + /******/ get: getter + /******/ }); + /******/ } + /******/ }; + /******/ + /******/ // getDefaultExport function for compatibility with non-harmony modules + /******/ __webpack_require__.n = function(module) { + /******/ var getter = module && module.__esModule ? + /******/ function getDefault() { return module['default']; } : + /******/ function getModuleExports() { return module; }; + /******/ __webpack_require__.d(getter, 'a', getter); + /******/ return getter; + /******/ }; + /******/ + /******/ // Object.prototype.hasOwnProperty.call + /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; + /******/ + /******/ // __webpack_public_path__ + /******/ __webpack_require__.p = ""; + /******/ + /******/ // Load entry module and return exports + /******/ return __webpack_require__(__webpack_require__.s = 5); + /******/ }) +/************************************************************************/ +/******/ ([ + /* 0 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + Object.defineProperty(exports, "__esModule", { + value: true + }); + var LS_ACCESS_TOKEN_KEY = exports.LS_ACCESS_TOKEN_KEY = 'gitment-comments-token'; + var LS_USER_KEY = exports.LS_USER_KEY = 'gitment-user-info'; + + var NOT_INITIALIZED_ERROR = exports.NOT_INITIALIZED_ERROR = new Error('Comments Not Initialized'); + + /***/ }), + /* 1 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + /* WEBPACK VAR INJECTION */(function(global) { + + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + + var __extends = undefined && undefined.__extends || function () { + var extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function (d, b) { + d.__proto__ = b; + } || function (d, b) { + for (var p in b) { + if (b.hasOwnProperty(p)) d[p] = b[p]; + } + }; + return function (d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; + }(); + Object.defineProperty(exports, "__esModule", { value: true }); + registerGlobals(); + exports.extras = { + allowStateChanges: allowStateChanges, + deepEqual: deepEqual, + getAtom: getAtom, + getDebugName: getDebugName, + getDependencyTree: getDependencyTree, + getAdministration: getAdministration, + getGlobalState: getGlobalState, + getObserverTree: getObserverTree, + isComputingDerivation: isComputingDerivation, + isSpyEnabled: isSpyEnabled, + onReactionError: onReactionError, + resetGlobalState: resetGlobalState, + shareGlobalState: shareGlobalState, + spyReport: spyReport, + spyReportEnd: spyReportEnd, + spyReportStart: spyReportStart, + setReactionScheduler: setReactionScheduler + }; + if ((typeof __MOBX_DEVTOOLS_GLOBAL_HOOK__ === "undefined" ? "undefined" : _typeof(__MOBX_DEVTOOLS_GLOBAL_HOOK__)) === "object") { + __MOBX_DEVTOOLS_GLOBAL_HOOK__.injectMobx(module.exports); + } + module.exports.default = module.exports; + var actionFieldDecorator = createClassPropertyDecorator(function (target, key, value, args, originalDescriptor) { + var actionName = args && args.length === 1 ? args[0] : value.name || key || ""; + var wrappedAction = action(actionName, value); + addHiddenProp(target, key, wrappedAction); + }, function (key) { + return this[key]; + }, function () { + invariant(false, getMessage("m001")); + }, false, true); + var boundActionDecorator = createClassPropertyDecorator(function (target, key, value) { + defineBoundAction(target, key, value); + }, function (key) { + return this[key]; + }, function () { + invariant(false, getMessage("m001")); + }, false, false); + var action = function action(arg1, arg2, arg3, arg4) { + if (arguments.length === 1 && typeof arg1 === "function") return createAction(arg1.name || "", arg1); + if (arguments.length === 2 && typeof arg2 === "function") return createAction(arg1, arg2); + if (arguments.length === 1 && typeof arg1 === "string") return namedActionDecorator(arg1); + return namedActionDecorator(arg2).apply(null, arguments); + }; + exports.action = action; + action.bound = function boundAction(arg1, arg2, arg3) { + if (typeof arg1 === "function") { + var action_1 = createAction("", arg1); + action_1.autoBind = true; + return action_1; + } + return boundActionDecorator.apply(null, arguments); + }; + function namedActionDecorator(name) { + return function (target, prop, descriptor) { + if (descriptor && typeof descriptor.value === "function") { + descriptor.value = createAction(name, descriptor.value); + descriptor.enumerable = false; + descriptor.configurable = true; + return descriptor; + } + return actionFieldDecorator(name).apply(this, arguments); + }; + } + function runInAction(arg1, arg2, arg3) { + var actionName = typeof arg1 === "string" ? arg1 : arg1.name || ""; + var fn = typeof arg1 === "function" ? arg1 : arg2; + var scope = typeof arg1 === "function" ? arg2 : arg3; + invariant(typeof fn === "function", getMessage("m002")); + invariant(fn.length === 0, getMessage("m003")); + invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'"); + return executeAction(actionName, fn, scope, undefined); + } + exports.runInAction = runInAction; + function isAction(thing) { + return typeof thing === "function" && thing.isMobxAction === true; + } + exports.isAction = isAction; + function defineBoundAction(target, propertyName, fn) { + var res = function res() { + return executeAction(propertyName, fn, target, arguments); + }; + res.isMobxAction = true; + addHiddenProp(target, propertyName, res); + } + function autorun(arg1, arg2, arg3) { + var name, view, scope; + if (typeof arg1 === "string") { + name = arg1; + view = arg2; + scope = arg3; + } else { + name = arg1.name || "Autorun@" + getNextId(); + view = arg1; + scope = arg2; + } + invariant(typeof view === "function", getMessage("m004")); + invariant(isAction(view) === false, getMessage("m005")); + if (scope) view = view.bind(scope); + var reaction = new Reaction(name, function () { + this.track(reactionRunner); + }); + function reactionRunner() { + view(reaction); + } + reaction.schedule(); + return reaction.getDisposer(); + } + exports.autorun = autorun; + function when(arg1, arg2, arg3, arg4) { + var name, predicate, effect, scope; + if (typeof arg1 === "string") { + name = arg1; + predicate = arg2; + effect = arg3; + scope = arg4; + } else { + name = "When@" + getNextId(); + predicate = arg1; + effect = arg2; + scope = arg3; + } + var disposer = autorun(name, function (r) { + if (predicate.call(scope)) { + r.dispose(); + var prevUntracked = untrackedStart(); + effect.call(scope); + untrackedEnd(prevUntracked); + } + }); + return disposer; + } + exports.when = when; + function autorunAsync(arg1, arg2, arg3, arg4) { + var name, func, delay, scope; + if (typeof arg1 === "string") { + name = arg1; + func = arg2; + delay = arg3; + scope = arg4; + } else { + name = arg1.name || "AutorunAsync@" + getNextId(); + func = arg1; + delay = arg2; + scope = arg3; + } + invariant(isAction(func) === false, getMessage("m006")); + if (delay === void 0) delay = 1; + if (scope) func = func.bind(scope); + var isScheduled = false; + var r = new Reaction(name, function () { + if (!isScheduled) { + isScheduled = true; + setTimeout(function () { + isScheduled = false; + if (!r.isDisposed) r.track(reactionRunner); + }, delay); + } + }); + function reactionRunner() { + func(r); + } + r.schedule(); + return r.getDisposer(); + } + exports.autorunAsync = autorunAsync; + function reaction(expression, effect, arg3) { + if (arguments.length > 3) { + fail(getMessage("m007")); + } + if (isModifierDescriptor(expression)) { + fail(getMessage("m008")); + } + var opts; + if ((typeof arg3 === "undefined" ? "undefined" : _typeof(arg3)) === "object") { + opts = arg3; + } else { + opts = {}; + } + opts.name = opts.name || expression.name || effect.name || "Reaction@" + getNextId(); + opts.fireImmediately = arg3 === true || opts.fireImmediately === true; + opts.delay = opts.delay || 0; + opts.compareStructural = opts.compareStructural || opts.struct || false; + effect = action(opts.name, opts.context ? effect.bind(opts.context) : effect); + if (opts.context) { + expression = expression.bind(opts.context); + } + var firstTime = true; + var isScheduled = false; + var nextValue; + var r = new Reaction(opts.name, function () { + if (firstTime || opts.delay < 1) { + reactionRunner(); + } else if (!isScheduled) { + isScheduled = true; + setTimeout(function () { + isScheduled = false; + reactionRunner(); + }, opts.delay); + } + }); + function reactionRunner() { + if (r.isDisposed) return; + var changed = false; + r.track(function () { + var v = expression(r); + changed = valueDidChange(opts.compareStructural, nextValue, v); + nextValue = v; + }); + if (firstTime && opts.fireImmediately) effect(nextValue, r); + if (!firstTime && changed === true) effect(nextValue, r); + if (firstTime) firstTime = false; + } + r.schedule(); + return r.getDisposer(); + } + exports.reaction = reaction; + function createComputedDecorator(compareStructural) { + return createClassPropertyDecorator(function (target, name, _, __, originalDescriptor) { + invariant(typeof originalDescriptor !== "undefined", getMessage("m009")); + invariant(typeof originalDescriptor.get === "function", getMessage("m010")); + var adm = asObservableObject(target, ""); + defineComputedProperty(adm, name, originalDescriptor.get, originalDescriptor.set, compareStructural, false); + }, function (name) { + var observable = this.$mobx.values[name]; + if (observable === undefined) return undefined; + return observable.get(); + }, function (name, value) { + this.$mobx.values[name].set(value); + }, false, false); + } + var computedDecorator = createComputedDecorator(false); + var computedStructDecorator = createComputedDecorator(true); + var computed = function computed(arg1, arg2, arg3) { + if (typeof arg2 === "string") { + return computedDecorator.apply(null, arguments); + } + invariant(typeof arg1 === "function", getMessage("m011")); + invariant(arguments.length < 3, getMessage("m012")); + var opts = (typeof arg2 === "undefined" ? "undefined" : _typeof(arg2)) === "object" ? arg2 : {}; + opts.setter = typeof arg2 === "function" ? arg2 : opts.setter; + return new ComputedValue(arg1, opts.context, opts.compareStructural || opts.struct || false, opts.name || arg1.name || "", opts.setter); + }; + exports.computed = computed; + computed.struct = computedStructDecorator; + function createTransformer(transformer, onCleanup) { + invariant(typeof transformer === "function" && transformer.length < 2, "createTransformer expects a function that accepts one argument"); + var objectCache = {}; + var resetId = globalState.resetId; + var Transformer = function (_super) { + __extends(Transformer, _super); + function Transformer(sourceIdentifier, sourceObject) { + var _this = _super.call(this, function () { + return transformer(sourceObject); + }, undefined, false, "Transformer-" + transformer.name + "-" + sourceIdentifier, undefined) || this; + _this.sourceIdentifier = sourceIdentifier; + _this.sourceObject = sourceObject; + return _this; + } + Transformer.prototype.onBecomeUnobserved = function () { + var lastValue = this.value; + _super.prototype.onBecomeUnobserved.call(this); + delete objectCache[this.sourceIdentifier]; + if (onCleanup) onCleanup(lastValue, this.sourceObject); + }; + return Transformer; + }(ComputedValue); + return function (object) { + if (resetId !== globalState.resetId) { + objectCache = {}; + resetId = globalState.resetId; + } + var identifier = getMemoizationId(object); + var reactiveTransformer = objectCache[identifier]; + if (reactiveTransformer) return reactiveTransformer.get(); + reactiveTransformer = objectCache[identifier] = new Transformer(identifier, object); + return reactiveTransformer.get(); + }; + } + exports.createTransformer = createTransformer; + function getMemoizationId(object) { + if (object === null || (typeof object === "undefined" ? "undefined" : _typeof(object)) !== "object") throw new Error("[mobx] transform expected some kind of object, got: " + object); + var tid = object.$transformId; + if (tid === undefined) { + tid = getNextId(); + addHiddenProp(object, "$transformId", tid); + } + return tid; + } + function expr(expr, scope) { + if (!isComputingDerivation()) console.warn(getMessage("m013")); + return computed(expr, { context: scope }).get(); + } + exports.expr = expr; + function extendObservable(target) { + var properties = []; + for (var _i = 1; _i < arguments.length; _i++) { + properties[_i - 1] = arguments[_i]; + } + return extendObservableHelper(target, deepEnhancer, properties); + } + exports.extendObservable = extendObservable; + function extendShallowObservable(target) { + var properties = []; + for (var _i = 1; _i < arguments.length; _i++) { + properties[_i - 1] = arguments[_i]; + } + return extendObservableHelper(target, referenceEnhancer, properties); + } + exports.extendShallowObservable = extendShallowObservable; + function extendObservableHelper(target, defaultEnhancer, properties) { + invariant(arguments.length >= 2, getMessage("m014")); + invariant((typeof target === "undefined" ? "undefined" : _typeof(target)) === "object", getMessage("m015")); + invariant(!isObservableMap(target), getMessage("m016")); + properties.forEach(function (propSet) { + invariant((typeof propSet === "undefined" ? "undefined" : _typeof(propSet)) === "object", getMessage("m017")); + invariant(!isObservable(propSet), getMessage("m018")); + }); + var adm = asObservableObject(target); + var definedProps = {}; + for (var i = properties.length - 1; i >= 0; i--) { + var propSet = properties[i]; + for (var key in propSet) { + if (definedProps[key] !== true && hasOwnProperty(propSet, key)) { + definedProps[key] = true; + if (target === propSet && !isPropertyConfigurable(target, key)) continue; + var descriptor = Object.getOwnPropertyDescriptor(propSet, key); + defineObservablePropertyFromDescriptor(adm, key, descriptor, defaultEnhancer); + } + } + } + return target; + } + function getDependencyTree(thing, property) { + return nodeToDependencyTree(getAtom(thing, property)); + } + function nodeToDependencyTree(node) { + var result = { + name: node.name + }; + if (node.observing && node.observing.length > 0) result.dependencies = unique(node.observing).map(nodeToDependencyTree); + return result; + } + function getObserverTree(thing, property) { + return nodeToObserverTree(getAtom(thing, property)); + } + function nodeToObserverTree(node) { + var result = { + name: node.name + }; + if (hasObservers(node)) result.observers = getObservers(node).map(nodeToObserverTree); + return result; + } + function intercept(thing, propOrHandler, handler) { + if (typeof handler === "function") return interceptProperty(thing, propOrHandler, handler);else return interceptInterceptable(thing, propOrHandler); + } + exports.intercept = intercept; + function interceptInterceptable(thing, handler) { + return getAdministration(thing).intercept(handler); + } + function interceptProperty(thing, property, handler) { + return getAdministration(thing, property).intercept(handler); + } + function isComputed(value, property) { + if (value === null || value === undefined) return false; + if (property !== undefined) { + if (isObservableObject(value) === false) return false; + var atom = getAtom(value, property); + return isComputedValue(atom); + } + return isComputedValue(value); + } + exports.isComputed = isComputed; + function isObservable(value, property) { + if (value === null || value === undefined) return false; + if (property !== undefined) { + if (isObservableArray(value) || isObservableMap(value)) throw new Error(getMessage("m019"));else if (isObservableObject(value)) { + var o = value.$mobx; + return o.values && !!o.values[property]; + } + return false; + } + return isObservableObject(value) || !!value.$mobx || isAtom(value) || isReaction(value) || isComputedValue(value); + } + exports.isObservable = isObservable; + var deepDecorator = createDecoratorForEnhancer(deepEnhancer); + var shallowDecorator = createDecoratorForEnhancer(shallowEnhancer); + var refDecorator = createDecoratorForEnhancer(referenceEnhancer); + var deepStructDecorator = createDecoratorForEnhancer(deepStructEnhancer); + var refStructDecorator = createDecoratorForEnhancer(refStructEnhancer); + function createObservable(v) { + if (v === void 0) { + v = undefined; + } + if (typeof arguments[1] === "string") return deepDecorator.apply(null, arguments); + invariant(arguments.length <= 1, getMessage("m021")); + invariant(!isModifierDescriptor(v), getMessage("m020")); + if (isObservable(v)) return v; + var res = deepEnhancer(v, undefined, undefined); + if (res !== v) return res; + return observable.box(v); + } + var IObservableFactories = function () { + function IObservableFactories() {} + IObservableFactories.prototype.box = function (value, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("box"); + return new ObservableValue(value, deepEnhancer, name); + }; + IObservableFactories.prototype.shallowBox = function (value, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("shallowBox"); + return new ObservableValue(value, referenceEnhancer, name); + }; + IObservableFactories.prototype.array = function (initialValues, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("array"); + return new ObservableArray(initialValues, deepEnhancer, name); + }; + IObservableFactories.prototype.shallowArray = function (initialValues, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("shallowArray"); + return new ObservableArray(initialValues, referenceEnhancer, name); + }; + IObservableFactories.prototype.map = function (initialValues, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("map"); + return new ObservableMap(initialValues, deepEnhancer, name); + }; + IObservableFactories.prototype.shallowMap = function (initialValues, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("shallowMap"); + return new ObservableMap(initialValues, referenceEnhancer, name); + }; + IObservableFactories.prototype.object = function (props, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("object"); + var res = {}; + asObservableObject(res, name); + extendObservable(res, props); + return res; + }; + IObservableFactories.prototype.shallowObject = function (props, name) { + if (arguments.length > 2) incorrectlyUsedAsDecorator("shallowObject"); + var res = {}; + asObservableObject(res, name); + extendShallowObservable(res, props); + return res; + }; + IObservableFactories.prototype.ref = function () { + if (arguments.length < 2) { + return createModifierDescriptor(referenceEnhancer, arguments[0]); + } else { + return refDecorator.apply(null, arguments); + } + }; + IObservableFactories.prototype.shallow = function () { + if (arguments.length < 2) { + return createModifierDescriptor(shallowEnhancer, arguments[0]); + } else { + return shallowDecorator.apply(null, arguments); + } + }; + IObservableFactories.prototype.deep = function () { + if (arguments.length < 2) { + return createModifierDescriptor(deepEnhancer, arguments[0]); + } else { + return deepDecorator.apply(null, arguments); + } + }; + IObservableFactories.prototype.struct = function () { + if (arguments.length < 2) { + return createModifierDescriptor(deepStructEnhancer, arguments[0]); + } else { + return deepStructDecorator.apply(null, arguments); + } + }; + return IObservableFactories; + }(); + exports.IObservableFactories = IObservableFactories; + var observable = createObservable; + exports.observable = observable; + Object.keys(IObservableFactories.prototype).forEach(function (key) { + return observable[key] = IObservableFactories.prototype[key]; + }); + observable.deep.struct = observable.struct; + observable.ref.struct = function () { + if (arguments.length < 2) { + return createModifierDescriptor(refStructEnhancer, arguments[0]); + } else { + return refStructDecorator.apply(null, arguments); + } + }; + function incorrectlyUsedAsDecorator(methodName) { + fail("Expected one or two arguments to observable." + methodName + ". Did you accidentally try to use observable." + methodName + " as decorator?"); + } + function createDecoratorForEnhancer(enhancer) { + invariant(!!enhancer, ":("); + return createClassPropertyDecorator(function (target, name, baseValue, _, baseDescriptor) { + assertPropertyConfigurable(target, name); + invariant(!baseDescriptor || !baseDescriptor.get, getMessage("m022")); + var adm = asObservableObject(target, undefined); + defineObservableProperty(adm, name, baseValue, enhancer); + }, function (name) { + var observable = this.$mobx.values[name]; + if (observable === undefined) return undefined; + return observable.get(); + }, function (name, value) { + setPropertyValue(this, name, value); + }, true, false); + } + function observe(thing, propOrCb, cbOrFire, fireImmediately) { + if (typeof cbOrFire === "function") return observeObservableProperty(thing, propOrCb, cbOrFire, fireImmediately);else return observeObservable(thing, propOrCb, cbOrFire); + } + exports.observe = observe; + function observeObservable(thing, listener, fireImmediately) { + return getAdministration(thing).observe(listener, fireImmediately); + } + function observeObservableProperty(thing, property, listener, fireImmediately) { + return getAdministration(thing, property).observe(listener, fireImmediately); + } + function toJS(source, detectCycles, __alreadySeen) { + if (detectCycles === void 0) { + detectCycles = true; + } + if (__alreadySeen === void 0) { + __alreadySeen = []; + } + function cache(value) { + if (detectCycles) __alreadySeen.push([source, value]); + return value; + } + if (isObservable(source)) { + if (detectCycles && __alreadySeen === null) __alreadySeen = []; + if (detectCycles && source !== null && (typeof source === "undefined" ? "undefined" : _typeof(source)) === "object") { + for (var i = 0, l = __alreadySeen.length; i < l; i++) { + if (__alreadySeen[i][0] === source) return __alreadySeen[i][1]; + } + } + if (isObservableArray(source)) { + var res = cache([]); + var toAdd = source.map(function (value) { + return toJS(value, detectCycles, __alreadySeen); + }); + res.length = toAdd.length; + for (var i = 0, l = toAdd.length; i < l; i++) { + res[i] = toAdd[i]; + }return res; + } + if (isObservableObject(source)) { + var res = cache({}); + for (var key in source) { + res[key] = toJS(source[key], detectCycles, __alreadySeen); + }return res; + } + if (isObservableMap(source)) { + var res_1 = cache({}); + source.forEach(function (value, key) { + return res_1[key] = toJS(value, detectCycles, __alreadySeen); + }); + return res_1; + } + if (isObservableValue(source)) return toJS(source.get(), detectCycles, __alreadySeen); + } + return source; + } + exports.toJS = toJS; + function transaction(action, thisArg) { + if (thisArg === void 0) { + thisArg = undefined; + } + deprecated(getMessage("m023")); + return runInTransaction.apply(undefined, arguments); + } + exports.transaction = transaction; + function runInTransaction(action, thisArg) { + if (thisArg === void 0) { + thisArg = undefined; + } + return executeAction("", action); + } + function log(msg) { + console.log(msg); + return msg; + } + function whyRun(thing, prop) { + switch (arguments.length) { + case 0: + thing = globalState.trackingDerivation; + if (!thing) return log(getMessage("m024")); + break; + case 2: + thing = getAtom(thing, prop); + break; + } + thing = getAtom(thing); + if (isComputedValue(thing)) return log(thing.whyRun());else if (isReaction(thing)) return log(thing.whyRun()); + return fail(getMessage("m025")); + } + exports.whyRun = whyRun; + function createAction(actionName, fn) { + invariant(typeof fn === "function", getMessage("m026")); + invariant(typeof actionName === "string" && actionName.length > 0, "actions should have valid names, got: '" + actionName + "'"); + var res = function res() { + return executeAction(actionName, fn, this, arguments); + }; + res.originalFn = fn; + res.isMobxAction = true; + return res; + } + function executeAction(actionName, fn, scope, args) { + var runInfo = startAction(actionName, fn, scope, args); + try { + return fn.apply(scope, args); + } finally { + endAction(runInfo); + } + } + function startAction(actionName, fn, scope, args) { + var notifySpy = isSpyEnabled() && !!actionName; + var startTime = 0; + if (notifySpy) { + startTime = Date.now(); + var l = args && args.length || 0; + var flattendArgs = new Array(l); + if (l > 0) for (var i = 0; i < l; i++) { + flattendArgs[i] = args[i]; + }spyReportStart({ + type: "action", + name: actionName, + fn: fn, + object: scope, + arguments: flattendArgs + }); + } + var prevDerivation = untrackedStart(); + startBatch(); + var prevAllowStateChanges = allowStateChangesStart(true); + return { + prevDerivation: prevDerivation, + prevAllowStateChanges: prevAllowStateChanges, + notifySpy: notifySpy, + startTime: startTime + }; + } + function endAction(runInfo) { + allowStateChangesEnd(runInfo.prevAllowStateChanges); + endBatch(); + untrackedEnd(runInfo.prevDerivation); + if (runInfo.notifySpy) spyReportEnd({ time: Date.now() - runInfo.startTime }); + } + function useStrict(strict) { + invariant(globalState.trackingDerivation === null, getMessage("m028")); + globalState.strictMode = strict; + globalState.allowStateChanges = !strict; + } + exports.useStrict = useStrict; + function isStrictModeEnabled() { + return globalState.strictMode; + } + exports.isStrictModeEnabled = isStrictModeEnabled; + function allowStateChanges(allowStateChanges, func) { + var prev = allowStateChangesStart(allowStateChanges); + var res; + try { + res = func(); + } finally { + allowStateChangesEnd(prev); + } + return res; + } + function allowStateChangesStart(allowStateChanges) { + var prev = globalState.allowStateChanges; + globalState.allowStateChanges = allowStateChanges; + return prev; + } + function allowStateChangesEnd(prev) { + globalState.allowStateChanges = prev; + } + var BaseAtom = function () { + function BaseAtom(name) { + if (name === void 0) { + name = "Atom@" + getNextId(); + } + this.name = name; + this.isPendingUnobservation = true; + this.observers = []; + this.observersIndexes = {}; + this.diffValue = 0; + this.lastAccessedBy = 0; + this.lowestObserverState = IDerivationState.NOT_TRACKING; + } + BaseAtom.prototype.onBecomeUnobserved = function () {}; + BaseAtom.prototype.reportObserved = function () { + reportObserved(this); + }; + BaseAtom.prototype.reportChanged = function () { + startBatch(); + propagateChanged(this); + endBatch(); + }; + BaseAtom.prototype.toString = function () { + return this.name; + }; + return BaseAtom; + }(); + exports.BaseAtom = BaseAtom; + var Atom = function (_super) { + __extends(Atom, _super); + function Atom(name, onBecomeObservedHandler, onBecomeUnobservedHandler) { + if (name === void 0) { + name = "Atom@" + getNextId(); + } + if (onBecomeObservedHandler === void 0) { + onBecomeObservedHandler = noop; + } + if (onBecomeUnobservedHandler === void 0) { + onBecomeUnobservedHandler = noop; + } + var _this = _super.call(this, name) || this; + _this.name = name; + _this.onBecomeObservedHandler = onBecomeObservedHandler; + _this.onBecomeUnobservedHandler = onBecomeUnobservedHandler; + _this.isPendingUnobservation = false; + _this.isBeingTracked = false; + return _this; + } + Atom.prototype.reportObserved = function () { + startBatch(); + _super.prototype.reportObserved.call(this); + if (!this.isBeingTracked) { + this.isBeingTracked = true; + this.onBecomeObservedHandler(); + } + endBatch(); + return !!globalState.trackingDerivation; + }; + Atom.prototype.onBecomeUnobserved = function () { + this.isBeingTracked = false; + this.onBecomeUnobservedHandler(); + }; + return Atom; + }(BaseAtom); + exports.Atom = Atom; + var isAtom = createInstanceofPredicate("Atom", BaseAtom); + var ComputedValue = function () { + function ComputedValue(derivation, scope, compareStructural, name, setter) { + this.derivation = derivation; + this.scope = scope; + this.compareStructural = compareStructural; + this.dependenciesState = IDerivationState.NOT_TRACKING; + this.observing = []; + this.newObserving = null; + this.isPendingUnobservation = false; + this.observers = []; + this.observersIndexes = {}; + this.diffValue = 0; + this.runId = 0; + this.lastAccessedBy = 0; + this.lowestObserverState = IDerivationState.UP_TO_DATE; + this.unboundDepsCount = 0; + this.__mapid = "#" + getNextId(); + this.value = undefined; + this.isComputing = false; + this.isRunningSetter = false; + this.name = name || "ComputedValue@" + getNextId(); + if (setter) this.setter = createAction(name + "-setter", setter); + } + ComputedValue.prototype.onBecomeStale = function () { + propagateMaybeChanged(this); + }; + ComputedValue.prototype.onBecomeUnobserved = function () { + invariant(this.dependenciesState !== IDerivationState.NOT_TRACKING, getMessage("m029")); + clearObserving(this); + this.value = undefined; + }; + ComputedValue.prototype.get = function () { + invariant(!this.isComputing, "Cycle detected in computation " + this.name, this.derivation); + if (globalState.inBatch === 0) { + startBatch(); + if (shouldCompute(this)) this.value = this.computeValue(false); + endBatch(); + } else { + reportObserved(this); + if (shouldCompute(this)) if (this.trackAndCompute()) propagateChangeConfirmed(this); + } + var result = this.value; + if (isCaughtException(result)) throw result.cause; + return result; + }; + ComputedValue.prototype.peek = function () { + var res = this.computeValue(false); + if (isCaughtException(res)) throw res.cause; + return res; + }; + ComputedValue.prototype.set = function (value) { + if (this.setter) { + invariant(!this.isRunningSetter, "The setter of computed value '" + this.name + "' is trying to update itself. Did you intend to update an _observable_ value, instead of the computed property?"); + this.isRunningSetter = true; + try { + this.setter.call(this.scope, value); + } finally { + this.isRunningSetter = false; + } + } else invariant(false, "[ComputedValue '" + this.name + "'] It is not possible to assign a new value to a computed value."); + }; + ComputedValue.prototype.trackAndCompute = function () { + if (isSpyEnabled()) { + spyReport({ + object: this.scope, + type: "compute", + fn: this.derivation + }); + } + var oldValue = this.value; + var newValue = this.value = this.computeValue(true); + return isCaughtException(newValue) || valueDidChange(this.compareStructural, newValue, oldValue); + }; + ComputedValue.prototype.computeValue = function (track) { + this.isComputing = true; + globalState.computationDepth++; + var res; + if (track) { + res = trackDerivedFunction(this, this.derivation, this.scope); + } else { + try { + res = this.derivation.call(this.scope); + } catch (e) { + res = new CaughtException(e); + } + } + globalState.computationDepth--; + this.isComputing = false; + return res; + }; + ; + ComputedValue.prototype.observe = function (listener, fireImmediately) { + var _this = this; + var firstTime = true; + var prevValue = undefined; + return autorun(function () { + var newValue = _this.get(); + if (!firstTime || fireImmediately) { + var prevU = untrackedStart(); + listener({ + type: "update", + object: _this, + newValue: newValue, + oldValue: prevValue + }); + untrackedEnd(prevU); + } + firstTime = false; + prevValue = newValue; + }); + }; + ComputedValue.prototype.toJSON = function () { + return this.get(); + }; + ComputedValue.prototype.toString = function () { + return this.name + "[" + this.derivation.toString() + "]"; + }; + ComputedValue.prototype.valueOf = function () { + return toPrimitive(this.get()); + }; + ; + ComputedValue.prototype.whyRun = function () { + var isTracking = Boolean(globalState.trackingDerivation); + var observing = unique(this.isComputing ? this.newObserving : this.observing).map(function (dep) { + return dep.name; + }); + var observers = unique(getObservers(this).map(function (dep) { + return dep.name; + })); + return "\nWhyRun? computation '" + this.name + "':\n * Running because: " + (isTracking ? "[active] the value of this computation is needed by a reaction" : this.isComputing ? "[get] The value of this computed was requested outside a reaction" : "[idle] not running at the moment") + "\n" + (this.dependenciesState === IDerivationState.NOT_TRACKING ? getMessage("m032") : " * This computation will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + (this.isComputing && isTracking ? " (... or any observable accessed during the remainder of the current run)" : "") + "\n\t" + getMessage("m038") + "\n\n * If the outcome of this computation changes, the following observers will be re-run:\n " + joinStrings(observers) + "\n"); + }; + return ComputedValue; + }(); + ComputedValue.prototype[primitiveSymbol()] = ComputedValue.prototype.valueOf; + var isComputedValue = createInstanceofPredicate("ComputedValue", ComputedValue); + var IDerivationState; + (function (IDerivationState) { + IDerivationState[IDerivationState["NOT_TRACKING"] = -1] = "NOT_TRACKING"; + IDerivationState[IDerivationState["UP_TO_DATE"] = 0] = "UP_TO_DATE"; + IDerivationState[IDerivationState["POSSIBLY_STALE"] = 1] = "POSSIBLY_STALE"; + IDerivationState[IDerivationState["STALE"] = 2] = "STALE"; + })(IDerivationState || (IDerivationState = {})); + exports.IDerivationState = IDerivationState; + var CaughtException = function () { + function CaughtException(cause) { + this.cause = cause; + } + return CaughtException; + }(); + function isCaughtException(e) { + return e instanceof CaughtException; + } + function shouldCompute(derivation) { + switch (derivation.dependenciesState) { + case IDerivationState.UP_TO_DATE: + return false; + case IDerivationState.NOT_TRACKING: + case IDerivationState.STALE: + return true; + case IDerivationState.POSSIBLY_STALE: + { + var prevUntracked = untrackedStart(); + var obs = derivation.observing, + l = obs.length; + for (var i = 0; i < l; i++) { + var obj = obs[i]; + if (isComputedValue(obj)) { + try { + obj.get(); + } catch (e) { + untrackedEnd(prevUntracked); + return true; + } + if (derivation.dependenciesState === IDerivationState.STALE) { + untrackedEnd(prevUntracked); + return true; + } + } + } + changeDependenciesStateTo0(derivation); + untrackedEnd(prevUntracked); + return false; + } + } + } + function isComputingDerivation() { + return globalState.trackingDerivation !== null; + } + function checkIfStateModificationsAreAllowed(atom) { + var hasObservers = atom.observers.length > 0; + if (globalState.computationDepth > 0 && hasObservers) fail(getMessage("m031") + atom.name); + if (!globalState.allowStateChanges && hasObservers) fail(getMessage(globalState.strictMode ? "m030a" : "m030b") + atom.name); + } + function trackDerivedFunction(derivation, f, context) { + changeDependenciesStateTo0(derivation); + derivation.newObserving = new Array(derivation.observing.length + 100); + derivation.unboundDepsCount = 0; + derivation.runId = ++globalState.runId; + var prevTracking = globalState.trackingDerivation; + globalState.trackingDerivation = derivation; + var result; + try { + result = f.call(context); + } catch (e) { + result = new CaughtException(e); + } + globalState.trackingDerivation = prevTracking; + bindDependencies(derivation); + return result; + } + function bindDependencies(derivation) { + var prevObserving = derivation.observing; + var observing = derivation.observing = derivation.newObserving; + derivation.newObserving = null; + var i0 = 0, + l = derivation.unboundDepsCount; + for (var i = 0; i < l; i++) { + var dep = observing[i]; + if (dep.diffValue === 0) { + dep.diffValue = 1; + if (i0 !== i) observing[i0] = dep; + i0++; + } + } + observing.length = i0; + l = prevObserving.length; + while (l--) { + var dep = prevObserving[l]; + if (dep.diffValue === 0) { + removeObserver(dep, derivation); + } + dep.diffValue = 0; + } + while (i0--) { + var dep = observing[i0]; + if (dep.diffValue === 1) { + dep.diffValue = 0; + addObserver(dep, derivation); + } + } + } + function clearObserving(derivation) { + var obs = derivation.observing; + var i = obs.length; + while (i--) { + removeObserver(obs[i], derivation); + }derivation.dependenciesState = IDerivationState.NOT_TRACKING; + obs.length = 0; + } + function untracked(action) { + var prev = untrackedStart(); + var res = action(); + untrackedEnd(prev); + return res; + } + exports.untracked = untracked; + function untrackedStart() { + var prev = globalState.trackingDerivation; + globalState.trackingDerivation = null; + return prev; + } + function untrackedEnd(prev) { + globalState.trackingDerivation = prev; + } + function changeDependenciesStateTo0(derivation) { + if (derivation.dependenciesState === IDerivationState.UP_TO_DATE) return; + derivation.dependenciesState = IDerivationState.UP_TO_DATE; + var obs = derivation.observing; + var i = obs.length; + while (i--) { + obs[i].lowestObserverState = IDerivationState.UP_TO_DATE; + } + } + var persistentKeys = ["mobxGuid", "resetId", "spyListeners", "strictMode", "runId"]; + var MobXGlobals = function () { + function MobXGlobals() { + this.version = 5; + this.trackingDerivation = null; + this.computationDepth = 0; + this.runId = 0; + this.mobxGuid = 0; + this.inBatch = 0; + this.pendingUnobservations = []; + this.pendingReactions = []; + this.isRunningReactions = false; + this.allowStateChanges = true; + this.strictMode = false; + this.resetId = 0; + this.spyListeners = []; + this.globalReactionErrorHandlers = []; + } + return MobXGlobals; + }(); + var globalState = new MobXGlobals(); + function shareGlobalState() { + var global = getGlobal(); + var ownState = globalState; + if (global.__mobservableTrackingStack || global.__mobservableViewStack) throw new Error("[mobx] An incompatible version of mobservable is already loaded."); + if (global.__mobxGlobal && global.__mobxGlobal.version !== ownState.version) throw new Error("[mobx] An incompatible version of mobx is already loaded."); + if (global.__mobxGlobal) globalState = global.__mobxGlobal;else global.__mobxGlobal = ownState; + } + function getGlobalState() { + return globalState; + } + function registerGlobals() {} + function resetGlobalState() { + globalState.resetId++; + var defaultGlobals = new MobXGlobals(); + for (var key in defaultGlobals) { + if (persistentKeys.indexOf(key) === -1) globalState[key] = defaultGlobals[key]; + }globalState.allowStateChanges = !globalState.strictMode; + } + function hasObservers(observable) { + return observable.observers && observable.observers.length > 0; + } + function getObservers(observable) { + return observable.observers; + } + function invariantObservers(observable) { + var list = observable.observers; + var map = observable.observersIndexes; + var l = list.length; + for (var i = 0; i < l; i++) { + var id = list[i].__mapid; + if (i) { + invariant(map[id] === i, "INTERNAL ERROR maps derivation.__mapid to index in list"); + } else { + invariant(!(id in map), "INTERNAL ERROR observer on index 0 shouldnt be held in map."); + } + } + invariant(list.length === 0 || Object.keys(map).length === list.length - 1, "INTERNAL ERROR there is no junk in map"); + } + function addObserver(observable, node) { + var l = observable.observers.length; + if (l) { + observable.observersIndexes[node.__mapid] = l; + } + observable.observers[l] = node; + if (observable.lowestObserverState > node.dependenciesState) observable.lowestObserverState = node.dependenciesState; + } + function removeObserver(observable, node) { + if (observable.observers.length === 1) { + observable.observers.length = 0; + queueForUnobservation(observable); + } else { + var list = observable.observers; + var map_1 = observable.observersIndexes; + var filler = list.pop(); + if (filler !== node) { + var index = map_1[node.__mapid] || 0; + if (index) { + map_1[filler.__mapid] = index; + } else { + delete map_1[filler.__mapid]; + } + list[index] = filler; + } + delete map_1[node.__mapid]; + } + } + function queueForUnobservation(observable) { + if (!observable.isPendingUnobservation) { + observable.isPendingUnobservation = true; + globalState.pendingUnobservations.push(observable); + } + } + function startBatch() { + globalState.inBatch++; + } + function endBatch() { + if (--globalState.inBatch === 0) { + runReactions(); + var list = globalState.pendingUnobservations; + for (var i = 0; i < list.length; i++) { + var observable_1 = list[i]; + observable_1.isPendingUnobservation = false; + if (observable_1.observers.length === 0) { + observable_1.onBecomeUnobserved(); + } + } + globalState.pendingUnobservations = []; + } + } + function reportObserved(observable) { + var derivation = globalState.trackingDerivation; + if (derivation !== null) { + if (derivation.runId !== observable.lastAccessedBy) { + observable.lastAccessedBy = derivation.runId; + derivation.newObserving[derivation.unboundDepsCount++] = observable; + } + } else if (observable.observers.length === 0) { + queueForUnobservation(observable); + } + } + function invariantLOS(observable, msg) { + var min = getObservers(observable).reduce(function (a, b) { + return Math.min(a, b.dependenciesState); + }, 2); + if (min >= observable.lowestObserverState) return; + throw new Error("lowestObserverState is wrong for " + msg + " because " + min + " < " + observable.lowestObserverState); + } + function propagateChanged(observable) { + if (observable.lowestObserverState === IDerivationState.STALE) return; + observable.lowestObserverState = IDerivationState.STALE; + var observers = observable.observers; + var i = observers.length; + while (i--) { + var d = observers[i]; + if (d.dependenciesState === IDerivationState.UP_TO_DATE) d.onBecomeStale(); + d.dependenciesState = IDerivationState.STALE; + } + } + function propagateChangeConfirmed(observable) { + if (observable.lowestObserverState === IDerivationState.STALE) return; + observable.lowestObserverState = IDerivationState.STALE; + var observers = observable.observers; + var i = observers.length; + while (i--) { + var d = observers[i]; + if (d.dependenciesState === IDerivationState.POSSIBLY_STALE) d.dependenciesState = IDerivationState.STALE;else if (d.dependenciesState === IDerivationState.UP_TO_DATE) observable.lowestObserverState = IDerivationState.UP_TO_DATE; + } + } + function propagateMaybeChanged(observable) { + if (observable.lowestObserverState !== IDerivationState.UP_TO_DATE) return; + observable.lowestObserverState = IDerivationState.POSSIBLY_STALE; + var observers = observable.observers; + var i = observers.length; + while (i--) { + var d = observers[i]; + if (d.dependenciesState === IDerivationState.UP_TO_DATE) { + d.dependenciesState = IDerivationState.POSSIBLY_STALE; + d.onBecomeStale(); + } + } + } + var Reaction = function () { + function Reaction(name, onInvalidate) { + if (name === void 0) { + name = "Reaction@" + getNextId(); + } + this.name = name; + this.onInvalidate = onInvalidate; + this.observing = []; + this.newObserving = []; + this.dependenciesState = IDerivationState.NOT_TRACKING; + this.diffValue = 0; + this.runId = 0; + this.unboundDepsCount = 0; + this.__mapid = "#" + getNextId(); + this.isDisposed = false; + this._isScheduled = false; + this._isTrackPending = false; + this._isRunning = false; + } + Reaction.prototype.onBecomeStale = function () { + this.schedule(); + }; + Reaction.prototype.schedule = function () { + if (!this._isScheduled) { + this._isScheduled = true; + globalState.pendingReactions.push(this); + runReactions(); + } + }; + Reaction.prototype.isScheduled = function () { + return this._isScheduled; + }; + Reaction.prototype.runReaction = function () { + if (!this.isDisposed) { + startBatch(); + this._isScheduled = false; + if (shouldCompute(this)) { + this._isTrackPending = true; + this.onInvalidate(); + if (this._isTrackPending && isSpyEnabled()) { + spyReport({ + object: this, + type: "scheduled-reaction" + }); + } + } + endBatch(); + } + }; + Reaction.prototype.track = function (fn) { + startBatch(); + var notify = isSpyEnabled(); + var startTime; + if (notify) { + startTime = Date.now(); + spyReportStart({ + object: this, + type: "reaction", + fn: fn + }); + } + this._isRunning = true; + var result = trackDerivedFunction(this, fn, undefined); + this._isRunning = false; + this._isTrackPending = false; + if (this.isDisposed) { + clearObserving(this); + } + if (isCaughtException(result)) this.reportExceptionInDerivation(result.cause); + if (notify) { + spyReportEnd({ + time: Date.now() - startTime + }); + } + endBatch(); + }; + Reaction.prototype.reportExceptionInDerivation = function (error) { + var _this = this; + if (this.errorHandler) { + this.errorHandler(error, this); + return; + } + var message = "[mobx] Encountered an uncaught exception that was thrown by a reaction or observer component, in: '" + this; + var messageToUser = getMessage("m037"); + console.error(message || messageToUser, error); + if (isSpyEnabled()) { + spyReport({ + type: "error", + message: message, + error: error, + object: this + }); + } + globalState.globalReactionErrorHandlers.forEach(function (f) { + return f(error, _this); + }); + }; + Reaction.prototype.dispose = function () { + if (!this.isDisposed) { + this.isDisposed = true; + if (!this._isRunning) { + startBatch(); + clearObserving(this); + endBatch(); + } + } + }; + Reaction.prototype.getDisposer = function () { + var r = this.dispose.bind(this); + r.$mobx = this; + r.onError = registerErrorHandler; + return r; + }; + Reaction.prototype.toString = function () { + return "Reaction[" + this.name + "]"; + }; + Reaction.prototype.whyRun = function () { + var observing = unique(this._isRunning ? this.newObserving : this.observing).map(function (dep) { + return dep.name; + }); + return "\nWhyRun? reaction '" + this.name + "':\n * Status: [" + (this.isDisposed ? "stopped" : this._isRunning ? "running" : this.isScheduled() ? "scheduled" : "idle") + "]\n * This reaction will re-run if any of the following observables changes:\n " + joinStrings(observing) + "\n " + (this._isRunning ? " (... or any observable accessed during the remainder of the current run)" : "") + "\n\t" + getMessage("m038") + "\n"; + }; + return Reaction; + }(); + exports.Reaction = Reaction; + function registerErrorHandler(handler) { + invariant(this && this.$mobx && isReaction(this.$mobx), "Invalid `this`"); + invariant(!this.$mobx.errorHandler, "Only one onErrorHandler can be registered"); + this.$mobx.errorHandler = handler; + } + function onReactionError(handler) { + globalState.globalReactionErrorHandlers.push(handler); + return function () { + var idx = globalState.globalReactionErrorHandlers.indexOf(handler); + if (idx >= 0) globalState.globalReactionErrorHandlers.splice(idx, 1); + }; + } + var MAX_REACTION_ITERATIONS = 100; + var reactionScheduler = function reactionScheduler(f) { + return f(); + }; + function runReactions() { + if (globalState.inBatch > 0 || globalState.isRunningReactions) return; + reactionScheduler(runReactionsHelper); + } + function runReactionsHelper() { + globalState.isRunningReactions = true; + var allReactions = globalState.pendingReactions; + var iterations = 0; + while (allReactions.length > 0) { + if (++iterations === MAX_REACTION_ITERATIONS) { + console.error("Reaction doesn't converge to a stable state after " + MAX_REACTION_ITERATIONS + " iterations." + (" Probably there is a cycle in the reactive function: " + allReactions[0])); + allReactions.splice(0); + } + var remainingReactions = allReactions.splice(0); + for (var i = 0, l = remainingReactions.length; i < l; i++) { + remainingReactions[i].runReaction(); + } + } + globalState.isRunningReactions = false; + } + var isReaction = createInstanceofPredicate("Reaction", Reaction); + function setReactionScheduler(fn) { + var baseScheduler = reactionScheduler; + reactionScheduler = function reactionScheduler(f) { + return fn(function () { + return baseScheduler(f); + }); + }; + } + function isSpyEnabled() { + return !!globalState.spyListeners.length; + } + function spyReport(event) { + if (!globalState.spyListeners.length) return; + var listeners = globalState.spyListeners; + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i](event); + } + } + function spyReportStart(event) { + var change = objectAssign({}, event, { spyReportStart: true }); + spyReport(change); + } + var END_EVENT = { spyReportEnd: true }; + function spyReportEnd(change) { + if (change) spyReport(objectAssign({}, change, END_EVENT));else spyReport(END_EVENT); + } + function spy(listener) { + globalState.spyListeners.push(listener); + return once(function () { + var idx = globalState.spyListeners.indexOf(listener); + if (idx !== -1) globalState.spyListeners.splice(idx, 1); + }); + } + exports.spy = spy; + function hasInterceptors(interceptable) { + return interceptable.interceptors && interceptable.interceptors.length > 0; + } + function registerInterceptor(interceptable, handler) { + var interceptors = interceptable.interceptors || (interceptable.interceptors = []); + interceptors.push(handler); + return once(function () { + var idx = interceptors.indexOf(handler); + if (idx !== -1) interceptors.splice(idx, 1); + }); + } + function interceptChange(interceptable, change) { + var prevU = untrackedStart(); + try { + var interceptors = interceptable.interceptors; + if (interceptors) for (var i = 0, l = interceptors.length; i < l; i++) { + change = interceptors[i](change); + invariant(!change || change.type, "Intercept handlers should return nothing or a change object"); + if (!change) break; + } + return change; + } finally { + untrackedEnd(prevU); + } + } + function hasListeners(listenable) { + return listenable.changeListeners && listenable.changeListeners.length > 0; + } + function registerListener(listenable, handler) { + var listeners = listenable.changeListeners || (listenable.changeListeners = []); + listeners.push(handler); + return once(function () { + var idx = listeners.indexOf(handler); + if (idx !== -1) listeners.splice(idx, 1); + }); + } + function notifyListeners(listenable, change) { + var prevU = untrackedStart(); + var listeners = listenable.changeListeners; + if (!listeners) return; + listeners = listeners.slice(); + for (var i = 0, l = listeners.length; i < l; i++) { + listeners[i](change); + } + untrackedEnd(prevU); + } + function asReference(value) { + deprecated("asReference is deprecated, use observable.ref instead"); + return observable.ref(value); + } + exports.asReference = asReference; + function asStructure(value) { + deprecated("asStructure is deprecated. Use observable.struct, computed.struct or reaction options instead."); + return observable.struct(value); + } + exports.asStructure = asStructure; + function asFlat(value) { + deprecated("asFlat is deprecated, use observable.shallow instead"); + return observable.shallow(value); + } + exports.asFlat = asFlat; + function asMap(data) { + deprecated("asMap is deprecated, use observable.map or observable.shallowMap instead"); + return observable.map(data || {}); + } + exports.asMap = asMap; + function isModifierDescriptor(thing) { + return (typeof thing === "undefined" ? "undefined" : _typeof(thing)) === "object" && thing !== null && thing.isMobxModifierDescriptor === true; + } + exports.isModifierDescriptor = isModifierDescriptor; + function createModifierDescriptor(enhancer, initialValue) { + invariant(!isModifierDescriptor(initialValue), "Modifiers cannot be nested"); + return { + isMobxModifierDescriptor: true, + initialValue: initialValue, + enhancer: enhancer + }; + } + function deepEnhancer(v, _, name) { + if (isModifierDescriptor(v)) fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it"); + if (isObservable(v)) return v; + if (Array.isArray(v)) return observable.array(v, name); + if (isPlainObject(v)) return observable.object(v, name); + if (isES6Map(v)) return observable.map(v, name); + return v; + } + function shallowEnhancer(v, _, name) { + if (isModifierDescriptor(v)) fail("You tried to assign a modifier wrapped value to a collection, please define modifiers when creating the collection, not when modifying it"); + if (v === undefined || v === null) return v; + if (isObservableObject(v) || isObservableArray(v) || isObservableMap(v)) return v; + if (Array.isArray(v)) return observable.shallowArray(v, name); + if (isPlainObject(v)) return observable.shallowObject(v, name); + if (isES6Map(v)) return observable.shallowMap(v, name); + return fail("The shallow modifier / decorator can only used in combination with arrays, objects and maps"); + } + function referenceEnhancer(newValue) { + return newValue; + } + function deepStructEnhancer(v, oldValue, name) { + if (deepEqual(v, oldValue)) return oldValue; + if (isObservable(v)) return v; + if (Array.isArray(v)) return new ObservableArray(v, deepStructEnhancer, name); + if (isES6Map(v)) return new ObservableMap(v, deepStructEnhancer, name); + if (isPlainObject(v)) { + var res = {}; + asObservableObject(res, name); + extendObservableHelper(res, deepStructEnhancer, [v]); + return res; + } + return v; + } + function refStructEnhancer(v, oldValue, name) { + if (deepEqual(v, oldValue)) return oldValue; + return v; + } + var MAX_SPLICE_SIZE = 10000; + var safariPrototypeSetterInheritanceBug = function () { + var v = false; + var p = {}; + Object.defineProperty(p, "0", { set: function set() { + v = true; + } }); + Object.create(p)["0"] = 1; + return v === false; + }(); + var OBSERVABLE_ARRAY_BUFFER_SIZE = 0; + var StubArray = function () { + function StubArray() {} + return StubArray; + }(); + StubArray.prototype = []; + var ObservableArrayAdministration = function () { + function ObservableArrayAdministration(name, enhancer, array, owned) { + this.array = array; + this.owned = owned; + this.lastKnownLength = 0; + this.interceptors = null; + this.changeListeners = null; + this.atom = new BaseAtom(name || "ObservableArray@" + getNextId()); + this.enhancer = function (newV, oldV) { + return enhancer(newV, oldV, name + "[..]"); + }; + } + ObservableArrayAdministration.prototype.intercept = function (handler) { + return registerInterceptor(this, handler); + }; + ObservableArrayAdministration.prototype.observe = function (listener, fireImmediately) { + if (fireImmediately === void 0) { + fireImmediately = false; + } + if (fireImmediately) { + listener({ + object: this.array, + type: "splice", + index: 0, + added: this.values.slice(), + addedCount: this.values.length, + removed: [], + removedCount: 0 + }); + } + return registerListener(this, listener); + }; + ObservableArrayAdministration.prototype.getArrayLength = function () { + this.atom.reportObserved(); + return this.values.length; + }; + ObservableArrayAdministration.prototype.setArrayLength = function (newLength) { + if (typeof newLength !== "number" || newLength < 0) throw new Error("[mobx.array] Out of range: " + newLength); + var currentLength = this.values.length; + if (newLength === currentLength) return;else if (newLength > currentLength) { + var newItems = new Array(newLength - currentLength); + for (var i = 0; i < newLength - currentLength; i++) { + newItems[i] = undefined; + }this.spliceWithArray(currentLength, 0, newItems); + } else this.spliceWithArray(newLength, currentLength - newLength); + }; + ObservableArrayAdministration.prototype.updateArrayLength = function (oldLength, delta) { + if (oldLength !== this.lastKnownLength) throw new Error("[mobx] Modification exception: the internal structure of an observable array was changed. Did you use peek() to change it?"); + this.lastKnownLength += delta; + if (delta > 0 && oldLength + delta + 1 > OBSERVABLE_ARRAY_BUFFER_SIZE) reserveArrayBuffer(oldLength + delta + 1); + }; + ObservableArrayAdministration.prototype.spliceWithArray = function (index, deleteCount, newItems) { + var _this = this; + checkIfStateModificationsAreAllowed(this.atom); + var length = this.values.length; + if (index === undefined) index = 0;else if (index > length) index = length;else if (index < 0) index = Math.max(0, length + index); + if (arguments.length === 1) deleteCount = length - index;else if (deleteCount === undefined || deleteCount === null) deleteCount = 0;else deleteCount = Math.max(0, Math.min(deleteCount, length - index)); + if (newItems === undefined) newItems = []; + if (hasInterceptors(this)) { + var change = interceptChange(this, { + object: this.array, + type: "splice", + index: index, + removedCount: deleteCount, + added: newItems + }); + if (!change) return EMPTY_ARRAY; + deleteCount = change.removedCount; + newItems = change.added; + } + newItems = newItems.map(function (v) { + return _this.enhancer(v, undefined); + }); + var lengthDelta = newItems.length - deleteCount; + this.updateArrayLength(length, lengthDelta); + var res = this.spliceItemsIntoValues(index, deleteCount, newItems); + if (deleteCount !== 0 || newItems.length !== 0) this.notifyArraySplice(index, newItems, res); + return res; + }; + ObservableArrayAdministration.prototype.spliceItemsIntoValues = function (index, deleteCount, newItems) { + if (newItems.length < MAX_SPLICE_SIZE) { + return (_a = this.values).splice.apply(_a, [index, deleteCount].concat(newItems)); + } else { + var res = this.values.slice(index, index + deleteCount); + this.values = this.values.slice(0, index).concat(newItems, this.values.slice(index + deleteCount)); + return res; + } + var _a; + }; + ObservableArrayAdministration.prototype.notifyArrayChildUpdate = function (index, newValue, oldValue) { + var notifySpy = !this.owned && isSpyEnabled(); + var notify = hasListeners(this); + var change = notify || notifySpy ? { + object: this.array, + type: "update", + index: index, newValue: newValue, oldValue: oldValue + } : null; + if (notifySpy) spyReportStart(change); + this.atom.reportChanged(); + if (notify) notifyListeners(this, change); + if (notifySpy) spyReportEnd(); + }; + ObservableArrayAdministration.prototype.notifyArraySplice = function (index, added, removed) { + var notifySpy = !this.owned && isSpyEnabled(); + var notify = hasListeners(this); + var change = notify || notifySpy ? { + object: this.array, + type: "splice", + index: index, removed: removed, added: added, + removedCount: removed.length, + addedCount: added.length + } : null; + if (notifySpy) spyReportStart(change); + this.atom.reportChanged(); + if (notify) notifyListeners(this, change); + if (notifySpy) spyReportEnd(); + }; + return ObservableArrayAdministration; + }(); + var ObservableArray = function (_super) { + __extends(ObservableArray, _super); + function ObservableArray(initialValues, enhancer, name, owned) { + if (name === void 0) { + name = "ObservableArray@" + getNextId(); + } + if (owned === void 0) { + owned = false; + } + var _this = _super.call(this) || this; + var adm = new ObservableArrayAdministration(name, enhancer, _this, owned); + addHiddenFinalProp(_this, "$mobx", adm); + if (initialValues && initialValues.length) { + adm.updateArrayLength(0, initialValues.length); + adm.values = initialValues.map(function (v) { + return enhancer(v, undefined, name + "[..]"); + }); + adm.notifyArraySplice(0, adm.values.slice(), EMPTY_ARRAY); + } else { + adm.values = []; + } + if (safariPrototypeSetterInheritanceBug) { + Object.defineProperty(adm.array, "0", ENTRY_0); + } + return _this; + } + ObservableArray.prototype.intercept = function (handler) { + return this.$mobx.intercept(handler); + }; + ObservableArray.prototype.observe = function (listener, fireImmediately) { + if (fireImmediately === void 0) { + fireImmediately = false; + } + return this.$mobx.observe(listener, fireImmediately); + }; + ObservableArray.prototype.clear = function () { + return this.splice(0); + }; + ObservableArray.prototype.concat = function () { + var arrays = []; + for (var _i = 0; _i < arguments.length; _i++) { + arrays[_i] = arguments[_i]; + } + this.$mobx.atom.reportObserved(); + return Array.prototype.concat.apply(this.peek(), arrays.map(function (a) { + return isObservableArray(a) ? a.peek() : a; + })); + }; + ObservableArray.prototype.replace = function (newItems) { + return this.$mobx.spliceWithArray(0, this.$mobx.values.length, newItems); + }; + ObservableArray.prototype.toJS = function () { + return this.slice(); + }; + ObservableArray.prototype.toJSON = function () { + return this.toJS(); + }; + ObservableArray.prototype.peek = function () { + return this.$mobx.values; + }; + ObservableArray.prototype.find = function (predicate, thisArg, fromIndex) { + if (fromIndex === void 0) { + fromIndex = 0; + } + this.$mobx.atom.reportObserved(); + var items = this.$mobx.values, + l = items.length; + for (var i = fromIndex; i < l; i++) { + if (predicate.call(thisArg, items[i], i, this)) return items[i]; + }return undefined; + }; + ObservableArray.prototype.splice = function (index, deleteCount) { + var newItems = []; + for (var _i = 2; _i < arguments.length; _i++) { + newItems[_i - 2] = arguments[_i]; + } + switch (arguments.length) { + case 0: + return []; + case 1: + return this.$mobx.spliceWithArray(index); + case 2: + return this.$mobx.spliceWithArray(index, deleteCount); + } + return this.$mobx.spliceWithArray(index, deleteCount, newItems); + }; + ObservableArray.prototype.spliceWithArray = function (index, deleteCount, newItems) { + return this.$mobx.spliceWithArray(index, deleteCount, newItems); + }; + ObservableArray.prototype.push = function () { + var items = []; + for (var _i = 0; _i < arguments.length; _i++) { + items[_i] = arguments[_i]; + } + var adm = this.$mobx; + adm.spliceWithArray(adm.values.length, 0, items); + return adm.values.length; + }; + ObservableArray.prototype.pop = function () { + return this.splice(Math.max(this.$mobx.values.length - 1, 0), 1)[0]; + }; + ObservableArray.prototype.shift = function () { + return this.splice(0, 1)[0]; + }; + ObservableArray.prototype.unshift = function () { + var items = []; + for (var _i = 0; _i < arguments.length; _i++) { + items[_i] = arguments[_i]; + } + var adm = this.$mobx; + adm.spliceWithArray(0, 0, items); + return adm.values.length; + }; + ObservableArray.prototype.reverse = function () { + this.$mobx.atom.reportObserved(); + var clone = this.slice(); + return clone.reverse.apply(clone, arguments); + }; + ObservableArray.prototype.sort = function (compareFn) { + this.$mobx.atom.reportObserved(); + var clone = this.slice(); + return clone.sort.apply(clone, arguments); + }; + ObservableArray.prototype.remove = function (value) { + var idx = this.$mobx.values.indexOf(value); + if (idx > -1) { + this.splice(idx, 1); + return true; + } + return false; + }; + ObservableArray.prototype.move = function (fromIndex, toIndex) { + function checkIndex(index) { + if (index < 0) { + throw new Error("[mobx.array] Index out of bounds: " + index + " is negative"); + } + var length = this.$mobx.values.length; + if (index >= length) { + throw new Error("[mobx.array] Index out of bounds: " + index + " is not smaller than " + length); + } + } + checkIndex.call(this, fromIndex); + checkIndex.call(this, toIndex); + if (fromIndex === toIndex) { + return; + } + var oldItems = this.$mobx.values; + var newItems; + if (fromIndex < toIndex) { + newItems = oldItems.slice(0, fromIndex).concat(oldItems.slice(fromIndex + 1, toIndex + 1), [oldItems[fromIndex]], oldItems.slice(toIndex + 1)); + } else { + newItems = oldItems.slice(0, toIndex).concat([oldItems[fromIndex]], oldItems.slice(toIndex, fromIndex), oldItems.slice(fromIndex + 1)); + } + this.replace(newItems); + }; + ObservableArray.prototype.toString = function () { + this.$mobx.atom.reportObserved(); + return Array.prototype.toString.apply(this.$mobx.values, arguments); + }; + ObservableArray.prototype.toLocaleString = function () { + this.$mobx.atom.reportObserved(); + return Array.prototype.toLocaleString.apply(this.$mobx.values, arguments); + }; + return ObservableArray; + }(StubArray); + declareIterator(ObservableArray.prototype, function () { + return arrayAsIterator(this.slice()); + }); + makeNonEnumerable(ObservableArray.prototype, ["constructor", "intercept", "observe", "clear", "concat", "replace", "toJS", "toJSON", "peek", "find", "splice", "spliceWithArray", "push", "pop", "shift", "unshift", "reverse", "sort", "remove", "move", "toString", "toLocaleString"]); + Object.defineProperty(ObservableArray.prototype, "length", { + enumerable: false, + configurable: true, + get: function get() { + return this.$mobx.getArrayLength(); + }, + set: function set(newLength) { + this.$mobx.setArrayLength(newLength); + } + }); + ["every", "filter", "forEach", "indexOf", "join", "lastIndexOf", "map", "reduce", "reduceRight", "slice", "some"].forEach(function (funcName) { + var baseFunc = Array.prototype[funcName]; + invariant(typeof baseFunc === "function", "Base function not defined on Array prototype: '" + funcName + "'"); + addHiddenProp(ObservableArray.prototype, funcName, function () { + this.$mobx.atom.reportObserved(); + return baseFunc.apply(this.$mobx.values, arguments); + }); + }); + var ENTRY_0 = { + configurable: true, + enumerable: false, + set: createArraySetter(0), + get: createArrayGetter(0) + }; + function createArrayBufferItem(index) { + var set = createArraySetter(index); + var get = createArrayGetter(index); + Object.defineProperty(ObservableArray.prototype, "" + index, { + enumerable: false, + configurable: true, + set: set, get: get + }); + } + function createArraySetter(index) { + return function (newValue) { + var adm = this.$mobx; + var values = adm.values; + if (index < values.length) { + checkIfStateModificationsAreAllowed(adm.atom); + var oldValue = values[index]; + if (hasInterceptors(adm)) { + var change = interceptChange(adm, { + type: "update", + object: adm.array, + index: index, newValue: newValue + }); + if (!change) return; + newValue = change.newValue; + } + newValue = adm.enhancer(newValue, oldValue); + var changed = newValue !== oldValue; + if (changed) { + values[index] = newValue; + adm.notifyArrayChildUpdate(index, newValue, oldValue); + } + } else if (index === values.length) { + adm.spliceWithArray(index, 0, [newValue]); + } else throw new Error("[mobx.array] Index out of bounds, " + index + " is larger than " + values.length); + }; + } + function createArrayGetter(index) { + return function () { + var impl = this.$mobx; + if (impl) { + if (index < impl.values.length) { + impl.atom.reportObserved(); + return impl.values[index]; + } + console.warn("[mobx.array] Attempt to read an array index (" + index + ") that is out of bounds (" + impl.values.length + "). Please check length first. Out of bound indices will not be tracked by MobX"); + } + return undefined; + }; + } + function reserveArrayBuffer(max) { + for (var index = OBSERVABLE_ARRAY_BUFFER_SIZE; index < max; index++) { + createArrayBufferItem(index); + }OBSERVABLE_ARRAY_BUFFER_SIZE = max; + } + reserveArrayBuffer(1000); + var isObservableArrayAdministration = createInstanceofPredicate("ObservableArrayAdministration", ObservableArrayAdministration); + function isObservableArray(thing) { + return isObject(thing) && isObservableArrayAdministration(thing.$mobx); + } + exports.isObservableArray = isObservableArray; + var ObservableMapMarker = {}; + var ObservableMap = function () { + function ObservableMap(initialData, enhancer, name) { + if (enhancer === void 0) { + enhancer = deepEnhancer; + } + if (name === void 0) { + name = "ObservableMap@" + getNextId(); + } + this.enhancer = enhancer; + this.name = name; + this.$mobx = ObservableMapMarker; + this._data = {}; + this._hasMap = {}; + this._keys = new ObservableArray(undefined, referenceEnhancer, this.name + ".keys()", true); + this.interceptors = null; + this.changeListeners = null; + this.merge(initialData); + } + ObservableMap.prototype._has = function (key) { + return typeof this._data[key] !== "undefined"; + }; + ObservableMap.prototype.has = function (key) { + if (!this.isValidKey(key)) return false; + key = "" + key; + if (this._hasMap[key]) return this._hasMap[key].get(); + return this._updateHasMapEntry(key, false).get(); + }; + ObservableMap.prototype.set = function (key, value) { + this.assertValidKey(key); + key = "" + key; + var hasKey = this._has(key); + if (hasInterceptors(this)) { + var change = interceptChange(this, { + type: hasKey ? "update" : "add", + object: this, + newValue: value, + name: key + }); + if (!change) return this; + value = change.newValue; + } + if (hasKey) { + this._updateValue(key, value); + } else { + this._addValue(key, value); + } + return this; + }; + ObservableMap.prototype.delete = function (key) { + var _this = this; + this.assertValidKey(key); + key = "" + key; + if (hasInterceptors(this)) { + var change = interceptChange(this, { + type: "delete", + object: this, + name: key + }); + if (!change) return false; + } + if (this._has(key)) { + var notifySpy = isSpyEnabled(); + var notify = hasListeners(this); + var change = notify || notifySpy ? { + type: "delete", + object: this, + oldValue: this._data[key].value, + name: key + } : null; + if (notifySpy) spyReportStart(change); + runInTransaction(function () { + _this._keys.remove(key); + _this._updateHasMapEntry(key, false); + var observable = _this._data[key]; + observable.setNewValue(undefined); + _this._data[key] = undefined; + }); + if (notify) notifyListeners(this, change); + if (notifySpy) spyReportEnd(); + return true; + } + return false; + }; + ObservableMap.prototype._updateHasMapEntry = function (key, value) { + var entry = this._hasMap[key]; + if (entry) { + entry.setNewValue(value); + } else { + entry = this._hasMap[key] = new ObservableValue(value, referenceEnhancer, this.name + "." + key + "?", false); + } + return entry; + }; + ObservableMap.prototype._updateValue = function (name, newValue) { + var observable = this._data[name]; + newValue = observable.prepareNewValue(newValue); + if (newValue !== UNCHANGED) { + var notifySpy = isSpyEnabled(); + var notify = hasListeners(this); + var change = notify || notifySpy ? { + type: "update", + object: this, + oldValue: observable.value, + name: name, newValue: newValue + } : null; + if (notifySpy) spyReportStart(change); + observable.setNewValue(newValue); + if (notify) notifyListeners(this, change); + if (notifySpy) spyReportEnd(); + } + }; + ObservableMap.prototype._addValue = function (name, newValue) { + var _this = this; + runInTransaction(function () { + var observable = _this._data[name] = new ObservableValue(newValue, _this.enhancer, _this.name + "." + name, false); + newValue = observable.value; + _this._updateHasMapEntry(name, true); + _this._keys.push(name); + }); + var notifySpy = isSpyEnabled(); + var notify = hasListeners(this); + var change = notify || notifySpy ? { + type: "add", + object: this, + name: name, newValue: newValue + } : null; + if (notifySpy) spyReportStart(change); + if (notify) notifyListeners(this, change); + if (notifySpy) spyReportEnd(); + }; + ObservableMap.prototype.get = function (key) { + key = "" + key; + if (this.has(key)) return this._data[key].get(); + return undefined; + }; + ObservableMap.prototype.keys = function () { + return arrayAsIterator(this._keys.slice()); + }; + ObservableMap.prototype.values = function () { + return arrayAsIterator(this._keys.map(this.get, this)); + }; + ObservableMap.prototype.entries = function () { + var _this = this; + return arrayAsIterator(this._keys.map(function (key) { + return [key, _this.get(key)]; + })); + }; + ObservableMap.prototype.forEach = function (callback, thisArg) { + var _this = this; + this.keys().forEach(function (key) { + return callback.call(thisArg, _this.get(key), key, _this); + }); + }; + ObservableMap.prototype.merge = function (other) { + var _this = this; + if (isObservableMap(other)) { + other = other.toJS(); + } + runInTransaction(function () { + if (isPlainObject(other)) Object.keys(other).forEach(function (key) { + return _this.set(key, other[key]); + });else if (Array.isArray(other)) other.forEach(function (_a) { + var key = _a[0], + value = _a[1]; + return _this.set(key, value); + });else if (isES6Map(other)) other.forEach(function (value, key) { + return _this.set(key, value); + });else if (other !== null && other !== undefined) fail("Cannot initialize map from " + other); + }); + return this; + }; + ObservableMap.prototype.clear = function () { + var _this = this; + runInTransaction(function () { + untracked(function () { + _this.keys().forEach(_this.delete, _this); + }); + }); + }; + ObservableMap.prototype.replace = function (values) { + var _this = this; + runInTransaction(function () { + _this.clear(); + _this.merge(values); + }); + return this; + }; + Object.defineProperty(ObservableMap.prototype, "size", { + get: function get() { + return this._keys.length; + }, + enumerable: true, + configurable: true + }); + ObservableMap.prototype.toJS = function () { + var _this = this; + var res = {}; + this.keys().forEach(function (key) { + return res[key] = _this.get(key); + }); + return res; + }; + ObservableMap.prototype.toJSON = function () { + return this.toJS(); + }; + ObservableMap.prototype.isValidKey = function (key) { + if (key === null || key === undefined) return false; + if (typeof key === "string" || typeof key === "number" || typeof key === "boolean") return true; + return false; + }; + ObservableMap.prototype.assertValidKey = function (key) { + if (!this.isValidKey(key)) throw new Error("[mobx.map] Invalid key: '" + key + "', only strings, numbers and booleans are accepted as key in observable maps."); + }; + ObservableMap.prototype.toString = function () { + var _this = this; + return this.name + "[{ " + this.keys().map(function (key) { + return key + ": " + ("" + _this.get(key)); + }).join(", ") + " }]"; + }; + ObservableMap.prototype.observe = function (listener, fireImmediately) { + invariant(fireImmediately !== true, getMessage("m033")); + return registerListener(this, listener); + }; + ObservableMap.prototype.intercept = function (handler) { + return registerInterceptor(this, handler); + }; + return ObservableMap; + }(); + exports.ObservableMap = ObservableMap; + declareIterator(ObservableMap.prototype, function () { + return this.entries(); + }); + function map(initialValues) { + deprecated("`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead"); + return observable.map(initialValues); + } + exports.map = map; + var isObservableMap = createInstanceofPredicate("ObservableMap", ObservableMap); + exports.isObservableMap = isObservableMap; + var ObservableObjectAdministration = function () { + function ObservableObjectAdministration(target, name) { + this.target = target; + this.name = name; + this.values = {}; + this.changeListeners = null; + this.interceptors = null; + } + ObservableObjectAdministration.prototype.observe = function (callback, fireImmediately) { + invariant(fireImmediately !== true, "`observe` doesn't support the fire immediately property for observable objects."); + return registerListener(this, callback); + }; + ObservableObjectAdministration.prototype.intercept = function (handler) { + return registerInterceptor(this, handler); + }; + return ObservableObjectAdministration; + }(); + function asObservableObject(target, name) { + if (isObservableObject(target)) return target.$mobx; + invariant(Object.isExtensible(target), getMessage("m035")); + if (!isPlainObject(target)) name = (target.constructor.name || "ObservableObject") + "@" + getNextId(); + if (!name) name = "ObservableObject@" + getNextId(); + var adm = new ObservableObjectAdministration(target, name); + addHiddenFinalProp(target, "$mobx", adm); + return adm; + } + function defineObservablePropertyFromDescriptor(adm, propName, descriptor, defaultEnhancer) { + if (adm.values[propName]) { + invariant("value" in descriptor, "The property " + propName + " in " + adm.name + " is already observable, cannot redefine it as computed property"); + adm.target[propName] = descriptor.value; + return; + } + if ("value" in descriptor) { + if (isModifierDescriptor(descriptor.value)) { + var modifierDescriptor = descriptor.value; + defineObservableProperty(adm, propName, modifierDescriptor.initialValue, modifierDescriptor.enhancer); + } else if (isAction(descriptor.value) && descriptor.value.autoBind === true) { + defineBoundAction(adm.target, propName, descriptor.value.originalFn); + } else if (isComputedValue(descriptor.value)) { + defineComputedPropertyFromComputedValue(adm, propName, descriptor.value); + } else { + defineObservableProperty(adm, propName, descriptor.value, defaultEnhancer); + } + } else { + defineComputedProperty(adm, propName, descriptor.get, descriptor.set, false, true); + } + } + function defineObservableProperty(adm, propName, newValue, enhancer) { + assertPropertyConfigurable(adm.target, propName); + if (hasInterceptors(adm)) { + var change = interceptChange(adm, { + object: adm.target, + name: propName, + type: "add", + newValue: newValue + }); + if (!change) return; + newValue = change.newValue; + } + var observable = adm.values[propName] = new ObservableValue(newValue, enhancer, adm.name + "." + propName, false); + newValue = observable.value; + Object.defineProperty(adm.target, propName, generateObservablePropConfig(propName)); + notifyPropertyAddition(adm, adm.target, propName, newValue); + } + function defineComputedProperty(adm, propName, getter, setter, compareStructural, asInstanceProperty) { + if (asInstanceProperty) assertPropertyConfigurable(adm.target, propName); + adm.values[propName] = new ComputedValue(getter, adm.target, compareStructural, adm.name + "." + propName, setter); + if (asInstanceProperty) { + Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName)); + } + } + function defineComputedPropertyFromComputedValue(adm, propName, computedValue) { + var name = adm.name + "." + propName; + computedValue.name = name; + if (!computedValue.scope) computedValue.scope = adm.target; + adm.values[propName] = computedValue; + Object.defineProperty(adm.target, propName, generateComputedPropConfig(propName)); + } + var observablePropertyConfigs = {}; + var computedPropertyConfigs = {}; + function generateObservablePropConfig(propName) { + return observablePropertyConfigs[propName] || (observablePropertyConfigs[propName] = { + configurable: true, + enumerable: true, + get: function get() { + return this.$mobx.values[propName].get(); + }, + set: function set(v) { + setPropertyValue(this, propName, v); + } + }); + } + function generateComputedPropConfig(propName) { + return computedPropertyConfigs[propName] || (computedPropertyConfigs[propName] = { + configurable: true, + enumerable: false, + get: function get() { + return this.$mobx.values[propName].get(); + }, + set: function set(v) { + return this.$mobx.values[propName].set(v); + } + }); + } + function setPropertyValue(instance, name, newValue) { + var adm = instance.$mobx; + var observable = adm.values[name]; + if (hasInterceptors(adm)) { + var change = interceptChange(adm, { + type: "update", + object: instance, + name: name, newValue: newValue + }); + if (!change) return; + newValue = change.newValue; + } + newValue = observable.prepareNewValue(newValue); + if (newValue !== UNCHANGED) { + var notify = hasListeners(adm); + var notifySpy = isSpyEnabled(); + var change = notify || notifySpy ? { + type: "update", + object: instance, + oldValue: observable.value, + name: name, newValue: newValue + } : null; + if (notifySpy) spyReportStart(change); + observable.setNewValue(newValue); + if (notify) notifyListeners(adm, change); + if (notifySpy) spyReportEnd(); + } + } + function notifyPropertyAddition(adm, object, name, newValue) { + var notify = hasListeners(adm); + var notifySpy = isSpyEnabled(); + var change = notify || notifySpy ? { + type: "add", + object: object, name: name, newValue: newValue + } : null; + if (notifySpy) spyReportStart(change); + if (notify) notifyListeners(adm, change); + if (notifySpy) spyReportEnd(); + } + var isObservableObjectAdministration = createInstanceofPredicate("ObservableObjectAdministration", ObservableObjectAdministration); + function isObservableObject(thing) { + if (isObject(thing)) { + runLazyInitializers(thing); + return isObservableObjectAdministration(thing.$mobx); + } + return false; + } + exports.isObservableObject = isObservableObject; + var UNCHANGED = {}; + var ObservableValue = function (_super) { + __extends(ObservableValue, _super); + function ObservableValue(value, enhancer, name, notifySpy) { + if (name === void 0) { + name = "ObservableValue@" + getNextId(); + } + if (notifySpy === void 0) { + notifySpy = true; + } + var _this = _super.call(this, name) || this; + _this.enhancer = enhancer; + _this.hasUnreportedChange = false; + _this.value = enhancer(value, undefined, name); + if (notifySpy && isSpyEnabled()) { + spyReport({ type: "create", object: _this, newValue: _this.value }); + } + return _this; + } + ObservableValue.prototype.set = function (newValue) { + var oldValue = this.value; + newValue = this.prepareNewValue(newValue); + if (newValue !== UNCHANGED) { + var notifySpy = isSpyEnabled(); + if (notifySpy) { + spyReportStart({ + type: "update", + object: this, + newValue: newValue, oldValue: oldValue + }); + } + this.setNewValue(newValue); + if (notifySpy) spyReportEnd(); + } + }; + ObservableValue.prototype.prepareNewValue = function (newValue) { + checkIfStateModificationsAreAllowed(this); + if (hasInterceptors(this)) { + var change = interceptChange(this, { object: this, type: "update", newValue: newValue }); + if (!change) return UNCHANGED; + newValue = change.newValue; + } + newValue = this.enhancer(newValue, this.value, this.name); + return this.value !== newValue ? newValue : UNCHANGED; + }; + ObservableValue.prototype.setNewValue = function (newValue) { + var oldValue = this.value; + this.value = newValue; + this.reportChanged(); + if (hasListeners(this)) { + notifyListeners(this, { + type: "update", + object: this, + newValue: newValue, + oldValue: oldValue + }); + } + }; + ObservableValue.prototype.get = function () { + this.reportObserved(); + return this.value; + }; + ObservableValue.prototype.intercept = function (handler) { + return registerInterceptor(this, handler); + }; + ObservableValue.prototype.observe = function (listener, fireImmediately) { + if (fireImmediately) listener({ + object: this, + type: "update", + newValue: this.value, + oldValue: undefined + }); + return registerListener(this, listener); + }; + ObservableValue.prototype.toJSON = function () { + return this.get(); + }; + ObservableValue.prototype.toString = function () { + return this.name + "[" + this.value + "]"; + }; + ObservableValue.prototype.valueOf = function () { + return toPrimitive(this.get()); + }; + return ObservableValue; + }(BaseAtom); + ObservableValue.prototype[primitiveSymbol()] = ObservableValue.prototype.valueOf; + var isObservableValue = createInstanceofPredicate("ObservableValue", ObservableValue); + exports.isBoxedObservable = isObservableValue; + function getAtom(thing, property) { + if ((typeof thing === "undefined" ? "undefined" : _typeof(thing)) === "object" && thing !== null) { + if (isObservableArray(thing)) { + invariant(property === undefined, getMessage("m036")); + return thing.$mobx.atom; + } + if (isObservableMap(thing)) { + var anyThing = thing; + if (property === undefined) return getAtom(anyThing._keys); + var observable_2 = anyThing._data[property] || anyThing._hasMap[property]; + invariant(!!observable_2, "the entry '" + property + "' does not exist in the observable map '" + getDebugName(thing) + "'"); + return observable_2; + } + runLazyInitializers(thing); + if (isObservableObject(thing)) { + if (!property) return fail("please specify a property"); + var observable_3 = thing.$mobx.values[property]; + invariant(!!observable_3, "no observable property '" + property + "' found on the observable object '" + getDebugName(thing) + "'"); + return observable_3; + } + if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) { + return thing; + } + } else if (typeof thing === "function") { + if (isReaction(thing.$mobx)) { + return thing.$mobx; + } + } + return fail("Cannot obtain atom from " + thing); + } + function getAdministration(thing, property) { + invariant(thing, "Expecting some object"); + if (property !== undefined) return getAdministration(getAtom(thing, property)); + if (isAtom(thing) || isComputedValue(thing) || isReaction(thing)) return thing; + if (isObservableMap(thing)) return thing; + runLazyInitializers(thing); + if (thing.$mobx) return thing.$mobx; + invariant(false, "Cannot obtain administration from " + thing); + } + function getDebugName(thing, property) { + var named; + if (property !== undefined) named = getAtom(thing, property);else if (isObservableObject(thing) || isObservableMap(thing)) named = getAdministration(thing);else named = getAtom(thing); + return named.name; + } + function createClassPropertyDecorator(onInitialize, _get, _set, enumerable, allowCustomArguments) { + function classPropertyDecorator(target, key, descriptor, customArgs, argLen) { + if (argLen === void 0) { + argLen = 0; + } + invariant(allowCustomArguments || quacksLikeADecorator(arguments), "This function is a decorator, but it wasn't invoked like a decorator"); + if (!descriptor) { + var newDescriptor = { + enumerable: enumerable, + configurable: true, + get: function get() { + if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true) typescriptInitializeProperty(this, key, undefined, onInitialize, customArgs, descriptor); + return _get.call(this, key); + }, + set: function set(v) { + if (!this.__mobxInitializedProps || this.__mobxInitializedProps[key] !== true) { + typescriptInitializeProperty(this, key, v, onInitialize, customArgs, descriptor); + } else { + _set.call(this, key, v); + } + } + }; + if (arguments.length < 3 || arguments.length === 5 && argLen < 3) { + Object.defineProperty(target, key, newDescriptor); + } + return newDescriptor; + } else { + if (!hasOwnProperty(target, "__mobxLazyInitializers")) { + addHiddenProp(target, "__mobxLazyInitializers", target.__mobxLazyInitializers && target.__mobxLazyInitializers.slice() || []); + } + var value_1 = descriptor.value, + initializer_1 = descriptor.initializer; + target.__mobxLazyInitializers.push(function (instance) { + onInitialize(instance, key, initializer_1 ? initializer_1.call(instance) : value_1, customArgs, descriptor); + }); + return { + enumerable: enumerable, configurable: true, + get: function get() { + if (this.__mobxDidRunLazyInitializers !== true) runLazyInitializers(this); + return _get.call(this, key); + }, + set: function set(v) { + if (this.__mobxDidRunLazyInitializers !== true) runLazyInitializers(this); + _set.call(this, key, v); + } + }; + } + } + if (allowCustomArguments) { + return function () { + if (quacksLikeADecorator(arguments)) return classPropertyDecorator.apply(null, arguments); + var outerArgs = arguments; + var argLen = arguments.length; + return function (target, key, descriptor) { + return classPropertyDecorator(target, key, descriptor, outerArgs, argLen); + }; + }; + } + return classPropertyDecorator; + } + function typescriptInitializeProperty(instance, key, v, onInitialize, customArgs, baseDescriptor) { + if (!hasOwnProperty(instance, "__mobxInitializedProps")) addHiddenProp(instance, "__mobxInitializedProps", {}); + instance.__mobxInitializedProps[key] = true; + onInitialize(instance, key, v, customArgs, baseDescriptor); + } + function runLazyInitializers(instance) { + if (instance.__mobxDidRunLazyInitializers === true) return; + if (instance.__mobxLazyInitializers) { + addHiddenProp(instance, "__mobxDidRunLazyInitializers", true); + instance.__mobxDidRunLazyInitializers && instance.__mobxLazyInitializers.forEach(function (initializer) { + return initializer(instance); + }); + } + } + function quacksLikeADecorator(args) { + return (args.length === 2 || args.length === 3) && typeof args[1] === "string"; + } + function iteratorSymbol() { + return typeof Symbol === "function" && Symbol.iterator || "@@iterator"; + } + var IS_ITERATING_MARKER = "__$$iterating"; + function arrayAsIterator(array) { + invariant(array[IS_ITERATING_MARKER] !== true, "Illegal state: cannot recycle array as iterator"); + addHiddenFinalProp(array, IS_ITERATING_MARKER, true); + var idx = -1; + addHiddenFinalProp(array, "next", function next() { + idx++; + return { + done: idx >= this.length, + value: idx < this.length ? this[idx] : undefined + }; + }); + return array; + } + function declareIterator(prototType, iteratorFactory) { + addHiddenFinalProp(prototType, iteratorSymbol(), iteratorFactory); + } + var messages = { + "m001": "It is not allowed to assign new values to @action fields", + "m002": "`runInAction` expects a function", + "m003": "`runInAction` expects a function without arguments", + "m004": "autorun expects a function", + "m005": "Warning: attempted to pass an action to autorun. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.", + "m006": "Warning: attempted to pass an action to autorunAsync. Actions are untracked and will not trigger on state changes. Use `reaction` or wrap only your state modification code in an action.", + "m007": "reaction only accepts 2 or 3 arguments. If migrating from MobX 2, please provide an options object", + "m008": "wrapping reaction expression in `asReference` is no longer supported, use options object instead", + "m009": "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'. It looks like it was used on a property.", + "m010": "@computed can only be used on getter functions, like: '@computed get myProps() { return ...; }'", + "m011": "First argument to `computed` should be an expression. If using computed as decorator, don't pass it arguments", + "m012": "computed takes one or two arguments if used as function", + "m013": "[mobx.expr] 'expr' should only be used inside other reactive functions.", + "m014": "extendObservable expected 2 or more arguments", + "m015": "extendObservable expects an object as first argument", + "m016": "extendObservable should not be used on maps, use map.merge instead", + "m017": "all arguments of extendObservable should be objects", + "m018": "extending an object with another observable (object) is not supported. Please construct an explicit propertymap, using `toJS` if need. See issue #540", + "m019": "[mobx.isObservable] isObservable(object, propertyName) is not supported for arrays and maps. Use map.has or array.length instead.", + "m020": "modifiers can only be used for individual object properties", + "m021": "observable expects zero or one arguments", + "m022": "@observable can not be used on getters, use @computed instead", + "m023": "Using `transaction` is deprecated, use `runInAction` or `(@)action` instead.", + "m024": "whyRun() can only be used if a derivation is active, or by passing an computed value / reaction explicitly. If you invoked whyRun from inside a computation; the computation is currently suspended but re-evaluating because somebody requested its value.", + "m025": "whyRun can only be used on reactions and computed values", + "m026": "`action` can only be invoked on functions", + "m028": "It is not allowed to set `useStrict` when a derivation is running", + "m029": "INTERNAL ERROR only onBecomeUnobserved shouldn't be called twice in a row", + "m030a": "Since strict-mode is enabled, changing observed observable values outside actions is not allowed. Please wrap the code in an `action` if this change is intended. Tried to modify: ", + "m030b": "Side effects like changing state are not allowed at this point. Are you trying to modify state from, for example, the render function of a React component? Tried to modify: ", + "m031": "Computed values are not allowed to not cause side effects by changing observables that are already being observed. Tried to modify: ", + "m032": "* This computation is suspended (not in use by any reaction) and won't run automatically.\n Didn't expect this computation to be suspended at this point?\n 1. Make sure this computation is used by a reaction (reaction, autorun, observer).\n 2. Check whether you are using this computation synchronously (in the same stack as they reaction that needs it).", + "m033": "`observe` doesn't support the fire immediately property for observable maps.", + "m034": "`mobx.map` is deprecated, use `new ObservableMap` or `mobx.observable.map` instead", + "m035": "Cannot make the designated object observable; it is not extensible", + "m036": "It is not possible to get index atoms from arrays", + "m037": "Hi there! I'm sorry you have just run into an exception.\nIf your debugger ends up here, know that some reaction (like the render() of an observer component, autorun or reaction)\nthrew an exception and that mobx caught it, to avoid that it brings the rest of your application down.\nThe original cause of the exception (the code that caused this reaction to run (again)), is still in the stack.\n\nHowever, more interesting is the actual stack trace of the error itself.\nHopefully the error is an instanceof Error, because in that case you can inspect the original stack of the error from where it was thrown.\nSee `error.stack` property, or press the very subtle \"(...)\" link you see near the console.error message that probably brought you here.\nThat stack is more interesting than the stack of this console.error itself.\n\nIf the exception you see is an exception you created yourself, make sure to use `throw new Error(\"Oops\")` instead of `throw \"Oops\"`,\nbecause the javascript environment will only preserve the original stack trace in the first form.\n\nYou can also make sure the debugger pauses the next time this very same exception is thrown by enabling \"Pause on caught exception\".\n(Note that it might pause on many other, unrelated exception as well).\n\nIf that all doesn't help you out, feel free to open an issue https://github.com/mobxjs/mobx/issues!\n", + "m038": "Missing items in this list?\n 1. Check whether all used values are properly marked as observable (use isObservable to verify)\n 2. Make sure you didn't dereference values too early. MobX observes props, not primitives. E.g: use 'person.name' instead of 'name' in your computation.\n" + }; + function getMessage(id) { + return messages[id]; + } + var EMPTY_ARRAY = []; + Object.freeze(EMPTY_ARRAY); + function getGlobal() { + return global; + } + function getNextId() { + return ++globalState.mobxGuid; + } + function fail(message, thing) { + invariant(false, message, thing); + throw "X"; + } + function invariant(check, message, thing) { + if (!check) throw new Error("[mobx] Invariant failed: " + message + (thing ? " in '" + thing + "'" : "")); + } + var deprecatedMessages = []; + function deprecated(msg) { + if (deprecatedMessages.indexOf(msg) !== -1) return false; + deprecatedMessages.push(msg); + console.error("[mobx] Deprecated: " + msg); + return true; + } + function once(func) { + var invoked = false; + return function () { + if (invoked) return; + invoked = true; + return func.apply(this, arguments); + }; + } + var noop = function noop() {}; + function unique(list) { + var res = []; + list.forEach(function (item) { + if (res.indexOf(item) === -1) res.push(item); + }); + return res; + } + function joinStrings(things, limit, separator) { + if (limit === void 0) { + limit = 100; + } + if (separator === void 0) { + separator = " - "; + } + if (!things) return ""; + var sliced = things.slice(0, limit); + return "" + sliced.join(separator) + (things.length > limit ? " (... and " + (things.length - limit) + "more)" : ""); + } + function isObject(value) { + return value !== null && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object"; + } + function isPlainObject(value) { + if (value === null || (typeof value === "undefined" ? "undefined" : _typeof(value)) !== "object") return false; + var proto = Object.getPrototypeOf(value); + return proto === Object.prototype || proto === null; + } + function objectAssign() { + var res = arguments[0]; + for (var i = 1, l = arguments.length; i < l; i++) { + var source = arguments[i]; + for (var key in source) { + if (hasOwnProperty(source, key)) { + res[key] = source[key]; + } + } + } + return res; + } + function valueDidChange(compareStructural, oldValue, newValue) { + if (typeof oldValue === 'number' && isNaN(oldValue)) { + return typeof newValue !== 'number' || !isNaN(newValue); + } + return compareStructural ? !deepEqual(oldValue, newValue) : oldValue !== newValue; + } + var prototypeHasOwnProperty = Object.prototype.hasOwnProperty; + function hasOwnProperty(object, propName) { + return prototypeHasOwnProperty.call(object, propName); + } + function makeNonEnumerable(object, propNames) { + for (var i = 0; i < propNames.length; i++) { + addHiddenProp(object, propNames[i], object[propNames[i]]); + } + } + function addHiddenProp(object, propName, value) { + Object.defineProperty(object, propName, { + enumerable: false, + writable: true, + configurable: true, + value: value + }); + } + function addHiddenFinalProp(object, propName, value) { + Object.defineProperty(object, propName, { + enumerable: false, + writable: false, + configurable: true, + value: value + }); + } + function isPropertyConfigurable(object, prop) { + var descriptor = Object.getOwnPropertyDescriptor(object, prop); + return !descriptor || descriptor.configurable !== false && descriptor.writable !== false; + } + function assertPropertyConfigurable(object, prop) { + invariant(isPropertyConfigurable(object, prop), "Cannot make property '" + prop + "' observable, it is not configurable and writable in the target object"); + } + function getEnumerableKeys(obj) { + var res = []; + for (var key in obj) { + res.push(key); + }return res; + } + function deepEqual(a, b) { + if (a === null && b === null) return true; + if (a === undefined && b === undefined) return true; + if ((typeof a === "undefined" ? "undefined" : _typeof(a)) !== "object") return a === b; + var aIsArray = isArrayLike(a); + var aIsMap = isMapLike(a); + if (aIsArray !== isArrayLike(b)) { + return false; + } else if (aIsMap !== isMapLike(b)) { + return false; + } else if (aIsArray) { + if (a.length !== b.length) return false; + for (var i = a.length - 1; i >= 0; i--) { + if (!deepEqual(a[i], b[i])) return false; + }return true; + } else if (aIsMap) { + if (a.size !== b.size) return false; + var equals_1 = true; + a.forEach(function (value, key) { + equals_1 = equals_1 && deepEqual(b.get(key), value); + }); + return equals_1; + } else if ((typeof a === "undefined" ? "undefined" : _typeof(a)) === "object" && (typeof b === "undefined" ? "undefined" : _typeof(b)) === "object") { + if (a === null || b === null) return false; + if (isMapLike(a) && isMapLike(b)) { + if (a.size !== b.size) return false; + return deepEqual(observable.shallowMap(a).entries(), observable.shallowMap(b).entries()); + } + if (getEnumerableKeys(a).length !== getEnumerableKeys(b).length) return false; + for (var prop in a) { + if (!(prop in b)) return false; + if (!deepEqual(a[prop], b[prop])) return false; + } + return true; + } + return false; + } + function createInstanceofPredicate(name, clazz) { + var propName = "isMobX" + name; + clazz.prototype[propName] = true; + return function (x) { + return isObject(x) && x[propName] === true; + }; + } + function isArrayLike(x) { + return Array.isArray(x) || isObservableArray(x); + } + exports.isArrayLike = isArrayLike; + function isMapLike(x) { + return isES6Map(x) || isObservableMap(x); + } + function isES6Map(thing) { + if (getGlobal().Map !== undefined && thing instanceof getGlobal().Map) return true; + return false; + } + function primitiveSymbol() { + return typeof Symbol === "function" && Symbol.toPrimitive || "@@toPrimitive"; + } + function toPrimitive(value) { + return value === null ? null : (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object" ? "" + value : value; + } + /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(4))) + + /***/ }), + /* 2 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + var _icons = __webpack_require__(6); + + var _constants = __webpack_require__(0); + + function renderHeader(_ref, instance) { + var meta = _ref.meta, + user = _ref.user, + reactions = _ref.reactions; + + var container = document.createElement('div'); + container.lang = "en-US"; + container.className = 'gitment-container gitment-header-container'; + + var likeButton = document.createElement('span'); + var likedReaction = reactions.find(function (reaction) { + return reaction.content === 'heart' && reaction.user.login === user.login; + }); + likeButton.className = 'gitment-header-like-btn'; + likeButton.innerHTML = '\n ' + _icons.heart + '\n ' + (likedReaction ? 'Unlike' : 'Like') + '\n ' + (meta.reactions && meta.reactions.heart ? ' \u2022 ' + meta.reactions.heart + ' Liked' : '') + '\n '; + + if (likedReaction) { + likeButton.classList.add('liked'); + likeButton.onclick = function () { + return instance.unlike(); + }; + } else { + likeButton.classList.remove('liked'); + likeButton.onclick = function () { + return instance.like(); + }; + } + container.appendChild(likeButton); + + var commentsCount = document.createElement('span'); + commentsCount.innerHTML = '\n ' + (meta.comments ? ' \u2022 ' + meta.comments + ' Comments' : '') + '\n '; + container.appendChild(commentsCount); + + var issueLink = document.createElement('a'); + issueLink.className = 'gitment-header-issue-link'; + issueLink.href = meta.html_url; + issueLink.target = '_blank'; + issueLink.innerText = 'Issue Page'; + container.appendChild(issueLink); + + return container; + } + + function renderComments(_ref2, instance) { + var meta = _ref2.meta, + comments = _ref2.comments, + commentReactions = _ref2.commentReactions, + currentPage = _ref2.currentPage, + user = _ref2.user, + error = _ref2.error; + + var container = document.createElement('div'); + container.lang = "en-US"; + container.className = 'gitment-container gitment-comments-container'; + + if (error) { + var errorBlock = document.createElement('div'); + errorBlock.className = 'gitment-comments-error'; + + if (error === _constants.NOT_INITIALIZED_ERROR && user.login && user.login.toLowerCase() === instance.owner.toLowerCase()) { + var initHint = document.createElement('div'); + var initButton = document.createElement('button'); + initButton.className = 'gitment-comments-init-btn'; + initButton.onclick = function () { + initButton.setAttribute('disabled', true); + instance.init().catch(function (e) { + initButton.removeAttribute('disabled'); + alert(e); + }); + }; + initButton.innerText = 'Initialize Comments'; + initHint.appendChild(initButton); + errorBlock.appendChild(initHint); + } else { + errorBlock.innerText = error; + } + container.appendChild(errorBlock); + return container; + } else if (comments === undefined) { + var loading = document.createElement('div'); + loading.innerText = 'Loading comments...'; + loading.className = 'gitment-comments-loading'; + container.appendChild(loading); + return container; + } else if (!comments.length) { + var emptyBlock = document.createElement('div'); + emptyBlock.className = 'gitment-comments-empty'; + emptyBlock.innerText = 'No Comment Yet'; + container.appendChild(emptyBlock); + return container; + } + + var commentsList = document.createElement('ul'); + commentsList.className = 'gitment-comments-list'; + + comments.forEach(function (comment) { + var createDate = new Date(comment.created_at); + var updateDate = new Date(comment.updated_at); + var commentItem = document.createElement('li'); + commentItem.className = 'gitment-comment'; + commentItem.innerHTML = '\n \n \n \n
\n
\n \n ' + comment.user.login + '\n \n commented on\n ' + createDate.toDateString() + '\n ' + (createDate.toString() !== updateDate.toString() ? ' \u2022 edited' : '') + '\n
' + _icons.heart + ' ' + (comment.reactions.heart || '') + '
\n
\n
' + comment.body_html + '
\n
\n '; + var likeButton = commentItem.querySelector('.gitment-comment-like-btn'); + var likedReaction = commentReactions[comment.id] && commentReactions[comment.id].find(function (reaction) { + return reaction.content === 'heart' && reaction.user.login === user.login; + }); + if (likedReaction) { + likeButton.classList.add('liked'); + likeButton.onclick = function () { + return instance.unlikeAComment(comment.id); + }; + } else { + likeButton.classList.remove('liked'); + likeButton.onclick = function () { + return instance.likeAComment(comment.id); + }; + } + + // dirty + // use a blank image to trigger height calculating when element rendered + var imgTrigger = document.createElement('img'); + var markdownBody = commentItem.querySelector('.gitment-comment-body'); + imgTrigger.className = 'gitment-hidden'; + imgTrigger.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + imgTrigger.onload = function () { + if (markdownBody.clientHeight > instance.maxCommentHeight) { + markdownBody.classList.add('gitment-comment-body-folded'); + markdownBody.style.maxHeight = instance.maxCommentHeight + 'px'; + markdownBody.title = 'Click to Expand'; + markdownBody.onclick = function () { + markdownBody.classList.remove('gitment-comment-body-folded'); + markdownBody.style.maxHeight = ''; + markdownBody.title = ''; + markdownBody.onclick = null; + }; + } + }; + commentItem.appendChild(imgTrigger); + + commentsList.appendChild(commentItem); + }); + + container.appendChild(commentsList); + + if (meta) { + var pageCount = Math.ceil(meta.comments / instance.perPage); + if (pageCount > 1) { + var pagination = document.createElement('ul'); + pagination.className = 'gitment-comments-pagination'; + + if (currentPage > 1) { + var previousButton = document.createElement('li'); + previousButton.className = 'gitment-comments-page-item'; + previousButton.innerText = 'Previous'; + previousButton.onclick = function () { + return instance.goto(currentPage - 1); + }; + pagination.appendChild(previousButton); + } + + var _loop = function _loop(i) { + var pageItem = document.createElement('li'); + pageItem.className = 'gitment-comments-page-item'; + pageItem.innerText = i; + pageItem.onclick = function () { + return instance.goto(i); + }; + if (currentPage === i) pageItem.classList.add('gitment-selected'); + pagination.appendChild(pageItem); + }; + + for (var i = 1; i <= pageCount; i++) { + _loop(i); + } + + if (currentPage < pageCount) { + var nextButton = document.createElement('li'); + nextButton.className = 'gitment-comments-page-item'; + nextButton.innerText = 'Next'; + nextButton.onclick = function () { + return instance.goto(currentPage + 1); + }; + pagination.appendChild(nextButton); + } + + container.appendChild(pagination); + } + } + + return container; + } + + function renderEditor(_ref3, instance) { + var user = _ref3.user, + error = _ref3.error; + + var container = document.createElement('div'); + container.lang = "en-US"; + container.className = 'gitment-container gitment-editor-container'; + + var shouldDisable = user.login && !error ? '' : 'disabled'; + var disabledTip = user.login ? '' : 'Login to Comment'; + container.innerHTML = '\n ' + (user.login ? '\n \n ' : user.isLoggingIn ? '
' + _icons.spinner + '
' : '\n ' + _icons.github + '\n ') + '\n \n
\n
\n \n \n
\n
\n
\n \n
\n
\n
\n
\n
\n
\n \n '; + if (user.login) { + container.querySelector('.gitment-editor-logout-link').onclick = function () { + return instance.logout(); + }; + } + + var writeField = container.querySelector('.gitment-editor-write-field'); + var previewField = container.querySelector('.gitment-editor-preview-field'); + + var textarea = writeField.querySelector('textarea'); + textarea.oninput = function () { + textarea.style.height = 'auto'; + var style = window.getComputedStyle(textarea, null); + var height = parseInt(style.height, 10); + var clientHeight = textarea.clientHeight; + var scrollHeight = textarea.scrollHeight; + if (clientHeight < scrollHeight) { + textarea.style.height = height + scrollHeight - clientHeight + 'px'; + } + }; + + var _container$querySelec = container.querySelectorAll('.gitment-editor-tab'), + _container$querySelec2 = _slicedToArray(_container$querySelec, 2), + writeTab = _container$querySelec2[0], + previewTab = _container$querySelec2[1]; + + writeTab.onclick = function () { + writeTab.classList.add('gitment-selected'); + previewTab.classList.remove('gitment-selected'); + writeField.classList.remove('gitment-hidden'); + previewField.classList.add('gitment-hidden'); + + textarea.focus(); + }; + previewTab.onclick = function () { + previewTab.classList.add('gitment-selected'); + writeTab.classList.remove('gitment-selected'); + previewField.classList.remove('gitment-hidden'); + writeField.classList.add('gitment-hidden'); + + var preview = previewField.querySelector('.gitment-editor-preview'); + var content = textarea.value.trim(); + if (!content) { + preview.innerText = 'Nothing to preview'; + return; + } + + preview.innerText = 'Loading preview...'; + instance.markdown(content).then(function (html) { + return preview.innerHTML = html; + }); + }; + + var submitButton = container.querySelector('.gitment-editor-submit'); + submitButton.onclick = function () { + submitButton.innerText = 'Submitting...'; + submitButton.setAttribute('disabled', true); + instance.post(textarea.value.trim()).then(function (data) { + textarea.value = ''; + textarea.style.height = 'auto'; + submitButton.removeAttribute('disabled'); + submitButton.innerText = 'Comment'; + }).catch(function (e) { + alert(e); + submitButton.removeAttribute('disabled'); + submitButton.innerText = 'Comment'; + }); + }; + + return container; + } + + function renderFooter() { + var container = document.createElement('div'); + container.lang = "en-US"; + container.className = 'gitment-container gitment-footer-container'; + container.innerHTML = '\n Powered by\n \n Gitment\n \n '; + return container; + } + + function render(state, instance) { + var container = document.createElement('div'); + container.lang = "en-US"; + container.className = 'gitment-container gitment-root-container'; + container.appendChild(instance.renderHeader(state, instance)); + container.appendChild(instance.renderComments(state, instance)); + container.appendChild(instance.renderEditor(state, instance)); + container.appendChild(instance.renderFooter(state, instance)); + return container; + } + + exports.default = { render: render, renderHeader: renderHeader, renderComments: renderComments, renderEditor: renderEditor, renderFooter: renderFooter }; + + /***/ }), + /* 3 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + Object.defineProperty(exports, "__esModule", { + value: true + }); + exports.http = exports.Query = exports.isString = undefined; + + var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + + exports.getTargetContainer = getTargetContainer; + + var _constants = __webpack_require__(0); + + var isString = exports.isString = function isString(s) { + return toString.call(s) === '[object String]'; + }; + + function getTargetContainer(container) { + var targetContainer = void 0; + if (container instanceof Element) { + targetContainer = container; + } else if (isString(container)) { + targetContainer = document.getElementById(container); + } else { + targetContainer = document.createElement('div'); + } + + return targetContainer; + } + + var Query = exports.Query = { + parse: function parse() { + var search = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location.search; + + if (!search) return {}; + var queryString = search[0] === '?' ? search.substring(1) : search; + var query = {}; + queryString.split('&').forEach(function (queryStr) { + var _queryStr$split = queryStr.split('='), + _queryStr$split2 = _slicedToArray(_queryStr$split, 2), + key = _queryStr$split2[0], + value = _queryStr$split2[1]; + + if (key) query[key] = value; + }); + + return query; + }, + stringify: function stringify(query) { + var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '?'; + + var queryString = Object.keys(query).map(function (key) { + return key + '=' + encodeURIComponent(query[key] || ''); + }).join('&'); + return queryString ? prefix + queryString : ''; + } + }; + + function ajaxFactory(method) { + return function (apiPath) { + var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var base = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'https://api.github.com'; + + var req = new XMLHttpRequest(); + var token = localStorage.getItem(_constants.LS_ACCESS_TOKEN_KEY); + + var url = '' + base + apiPath; + var body = null; + if (method === 'GET' || method === 'DELETE') { + url += Query.stringify(data); + } + + var p = new Promise(function (resolve, reject) { + req.addEventListener('load', function () { + var contentType = req.getResponseHeader('content-type'); + var res = req.responseText; + if (!/json/.test(contentType)) { + resolve(res); + return; + } + var data = req.responseText ? JSON.parse(res) : {}; + if (data.message) { + reject(new Error(data.message)); + } else { + resolve(data); + } + }); + req.addEventListener('error', function (error) { + return reject(error); + }); + }); + req.open(method, url, true); + + req.setRequestHeader('Accept', 'application/vnd.github.squirrel-girl-preview, application/vnd.github.html+json'); + if (token) { + req.setRequestHeader('Authorization', 'token ' + token); + } + if (method !== 'GET' && method !== 'DELETE') { + body = JSON.stringify(data); + req.setRequestHeader('Content-Type', 'application/json'); + } + + req.send(body); + return p; + }; + } + + var http = exports.http = { + get: ajaxFactory('GET'), + post: ajaxFactory('POST'), + delete: ajaxFactory('DELETE'), + put: ajaxFactory('PUT') + }; + + /***/ }), + /* 4 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + + var g; + +// This works in non-strict mode + g = function () { + return this; + }(); + + try { + // This works if eval is allowed (see CSP) + g = g || Function("return this")() || (1, eval)("this"); + } catch (e) { + // This works if the window reference is available + if ((typeof window === "undefined" ? "undefined" : _typeof(window)) === "object") g = window; + } + +// g can still be undefined, but nothing to do about it... +// We return undefined, instead of nothing here, so it's +// easier to handle this case. if(!global) { ...} + + module.exports = g; + + /***/ }), + /* 5 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + + var _mobx = __webpack_require__(1); + + var _constants = __webpack_require__(0); + + var _utils = __webpack_require__(3); + + var _default = __webpack_require__(2); + + var _default2 = _interopRequireDefault(_default); + + function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + + var scope = 'public_repo'; + + function extendRenderer(instance, renderer) { + instance[renderer] = function (container) { + var targetContainer = (0, _utils.getTargetContainer)(container); + var render = instance.theme[renderer] || instance.defaultTheme[renderer]; + + (0, _mobx.autorun)(function () { + var e = render(instance.state, instance); + if (targetContainer.firstChild) { + targetContainer.replaceChild(e, targetContainer.firstChild); + } else { + targetContainer.appendChild(e); + } + }); + + return targetContainer; + }; + } + + var Gitment = function () { + _createClass(Gitment, [{ + key: 'accessToken', + get: function get() { + return localStorage.getItem(_constants.LS_ACCESS_TOKEN_KEY); + }, + set: function set(token) { + localStorage.setItem(_constants.LS_ACCESS_TOKEN_KEY, token); + } + }, { + key: 'loginLink', + get: function get() { + var oauthUri = 'https://github.com/login/oauth/authorize'; + var redirect_uri = this.oauth.redirect_uri || window.location.href; + + var oauthParams = Object.assign({ + scope: scope, + redirect_uri: redirect_uri + }, this.oauth); + + return '' + oauthUri + _utils.Query.stringify(oauthParams); + } + }]); + + function Gitment() { + var _this = this; + + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + _classCallCheck(this, Gitment); + + this.defaultTheme = _default2.default; + this.useTheme(_default2.default); + + Object.assign(this, { + id: window.location.href, + title: window.document.title, + link: window.location.href, + desc: '', + labels: [], + theme: _default2.default, + oauth: {}, + perPage: 20, + maxCommentHeight: 250 + }, options); + + this.useTheme(this.theme); + + var user = {}; + try { + var userInfo = localStorage.getItem(_constants.LS_USER_KEY); + if (this.accessToken && userInfo) { + Object.assign(user, JSON.parse(userInfo), { + fromCache: true + }); + } + } catch (e) { + localStorage.removeItem(_constants.LS_USER_KEY); + } + + this.state = (0, _mobx.observable)({ + user: user, + error: null, + meta: {}, + comments: undefined, + reactions: [], + commentReactions: {}, + currentPage: 1 + }); + + var query = _utils.Query.parse(); + if (query.code) { + var _oauth = this.oauth, + client_id = _oauth.client_id, + client_secret = _oauth.client_secret; + + var code = query.code; + delete query.code; + var search = _utils.Query.stringify(query); + var replacedUrl = '' + window.location.origin + window.location.pathname + search + window.location.hash; + history.replaceState({}, '', replacedUrl); + + Object.assign(this, { + id: replacedUrl, + link: replacedUrl + }, options); + + this.state.user.isLoggingIn = true; + _utils.http.post('https://gh-oauth.imsun.net', { + code: code, + client_id: client_id, + client_secret: client_secret + }, '').then(function (data) { + _this.accessToken = data.access_token; + _this.update(); + }).catch(function (e) { + _this.state.user.isLoggingIn = false; + alert(e); + }); + } else { + this.update(); + } + } + + _createClass(Gitment, [{ + key: 'init', + value: function init() { + var _this2 = this; + + return this.createIssue().then(function () { + return _this2.loadComments(); + }).then(function (comments) { + _this2.state.error = null; + return comments; + }); + } + }, { + key: 'useTheme', + value: function useTheme() { + var _this3 = this; + + var theme = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + + this.theme = theme; + + var renderers = Object.keys(this.theme); + renderers.forEach(function (renderer) { + return extendRenderer(_this3, renderer); + }); + } + }, { + key: 'update', + value: function update() { + var _this4 = this; + + return Promise.all([this.loadMeta(), this.loadUserInfo()]).then(function () { + return Promise.all([_this4.loadComments().then(function () { + return _this4.loadCommentReactions(); + }), _this4.loadReactions()]); + }).catch(function (e) { + return _this4.state.error = e; + }); + } + }, { + key: 'markdown', + value: function markdown(text) { + return _utils.http.post('/markdown', { + text: text, + mode: 'gfm' + }); + } + }, { + key: 'createIssue', + value: function createIssue() { + var _this5 = this; + + var id = this.id, + owner = this.owner, + repo = this.repo, + title = this.title, + link = this.link, + desc = this.desc, + labels = this.labels; + + + return _utils.http.post('/repos/' + owner + '/' + repo + '/issues', { + title: title, + labels: labels.concat(['gitment', id]), + body: link + '\n\n' + desc + }).then(function (meta) { + _this5.state.meta = meta; + return meta; + }); + } + }, { + key: 'getIssue', + value: function getIssue() { + if (this.state.meta.id) return Promise.resolve(this.state.meta); + + return this.loadMeta(); + } + }, { + key: 'post', + value: function post(body) { + var _this6 = this; + + return this.getIssue().then(function (issue) { + return _utils.http.post(issue.comments_url, { body: body }, ''); + }).then(function (data) { + _this6.state.meta.comments++; + var pageCount = Math.ceil(_this6.state.meta.comments / _this6.perPage); + if (_this6.state.currentPage === pageCount) { + _this6.state.comments.push(data); + } + return data; + }); + } + }, { + key: 'loadMeta', + value: function loadMeta() { + var _this7 = this; + + var id = this.id, + owner = this.owner, + repo = this.repo; + + return _utils.http.get('/repos/' + owner + '/' + repo + '/issues', { + creator: owner, + labels: id + }).then(function (issues) { + if (!issues.length) return Promise.reject(_constants.NOT_INITIALIZED_ERROR); + _this7.state.meta = issues[0]; + return issues[0]; + }); + } + }, { + key: 'loadComments', + value: function loadComments() { + var _this8 = this; + + var page = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state.currentPage; + + return this.getIssue().then(function (issue) { + return _utils.http.get(issue.comments_url, { page: page, per_page: _this8.perPage }, ''); + }).then(function (comments) { + _this8.state.comments = comments; + return comments; + }); + } + }, { + key: 'loadUserInfo', + value: function loadUserInfo() { + var _this9 = this; + + if (!this.accessToken) { + this.logout(); + return Promise.resolve({}); + } + + return _utils.http.get('/user').then(function (user) { + _this9.state.user = user; + localStorage.setItem(_constants.LS_USER_KEY, JSON.stringify(user)); + return user; + }); + } + }, { + key: 'loadReactions', + value: function loadReactions() { + var _this10 = this; + + if (!this.accessToken) { + this.state.reactions = []; + return Promise.resolve([]); + } + + return this.getIssue().then(function (issue) { + if (!issue.reactions.total_count) return []; + return _utils.http.get(issue.reactions.url, {}, ''); + }).then(function (reactions) { + _this10.state.reactions = reactions; + return reactions; + }); + } + }, { + key: 'loadCommentReactions', + value: function loadCommentReactions() { + var _this11 = this; + + if (!this.accessToken) { + this.state.commentReactions = {}; + return Promise.resolve([]); + } + + var comments = this.state.comments; + var comentReactions = {}; + + return Promise.all(comments.map(function (comment) { + if (!comment.reactions.total_count) return []; + + var owner = _this11.owner, + repo = _this11.repo; + + return _utils.http.get('/repos/' + owner + '/' + repo + '/issues/comments/' + comment.id + '/reactions', {}); + })).then(function (reactionsArray) { + comments.forEach(function (comment, index) { + comentReactions[comment.id] = reactionsArray[index]; + }); + _this11.state.commentReactions = comentReactions; + + return comentReactions; + }); + } + }, { + key: 'login', + value: function login() { + window.location.href = this.loginLink; + } + }, { + key: 'logout', + value: function logout() { + localStorage.removeItem(_constants.LS_ACCESS_TOKEN_KEY); + localStorage.removeItem(_constants.LS_USER_KEY); + this.state.user = {}; + } + }, { + key: 'goto', + value: function goto(page) { + this.state.currentPage = page; + this.state.comments = undefined; + return this.loadComments(page); + } + }, { + key: 'like', + value: function like() { + var _this12 = this; + + if (!this.accessToken) { + alert('Login to Like'); + return Promise.reject(); + } + + var owner = this.owner, + repo = this.repo; + + + return _utils.http.post('/repos/' + owner + '/' + repo + '/issues/' + this.state.meta.number + '/reactions', { + content: 'heart' + }).then(function (reaction) { + _this12.state.reactions.push(reaction); + _this12.state.meta.reactions.heart++; + }); + } + }, { + key: 'unlike', + value: function unlike() { + var _this13 = this; + + if (!this.accessToken) return Promise.reject(); + + var _state = this.state, + user = _state.user, + reactions = _state.reactions; + + var index = reactions.findIndex(function (reaction) { + return reaction.user.login === user.login; + }); + return _utils.http.delete('/reactions/' + reactions[index].id).then(function () { + reactions.splice(index, 1); + _this13.state.meta.reactions.heart--; + }); + } + }, { + key: 'likeAComment', + value: function likeAComment(commentId) { + var _this14 = this; + + if (!this.accessToken) { + alert('Login to Like'); + return Promise.reject(); + } + + var owner = this.owner, + repo = this.repo; + + var comment = this.state.comments.find(function (comment) { + return comment.id === commentId; + }); + + return _utils.http.post('/repos/' + owner + '/' + repo + '/issues/comments/' + commentId + '/reactions', { + content: 'heart' + }).then(function (reaction) { + _this14.state.commentReactions[commentId].push(reaction); + comment.reactions.heart++; + }); + } + }, { + key: 'unlikeAComment', + value: function unlikeAComment(commentId) { + if (!this.accessToken) return Promise.reject(); + + var reactions = this.state.commentReactions[commentId]; + var comment = this.state.comments.find(function (comment) { + return comment.id === commentId; + }); + var user = this.state.user; + + var index = reactions.findIndex(function (reaction) { + return reaction.user.login === user.login; + }); + + return _utils.http.delete('/reactions/' + reactions[index].id).then(function () { + reactions.splice(index, 1); + comment.reactions.heart--; + }); + } + }]); + + return Gitment; + }(); + + module.exports = Gitment; + + /***/ }), + /* 6 */ + /***/ (function(module, exports, __webpack_require__) { + + "use strict"; + + + Object.defineProperty(exports, "__esModule", { + value: true + }); + /** + * Modified from https://github.com/evil-icons/evil-icons + */ + + var close = exports.close = ''; + var github = exports.github = ''; + var heart = exports.heart = ''; + var spinner = exports.spinner = ''; + + /***/ }) + /******/ ]); +//# sourceMappingURL=gitment.browser.js.map \ No newline at end of file diff --git a/js/index.js b/js/index.js index e69de29..776bbb9 100644 --- a/js/index.js +++ b/js/index.js @@ -0,0 +1,348 @@ +/** + * Created by Xiaotao.Nie on 09/04/2018. + * All right reserved + * IF you have any question please email onlythen@yeah.net + */ + +// Global functions and listeners +window.onresize = () => { + // when window resize , we show remove some class that me be added + // often for debug + if(window.document.documentElement.clientWidth > 680){ + let aboutContent = document.getElementById('nav-content') + aboutContent.classList.remove('hide-block') + aboutContent.classList.remove('show-block'); + } + // if(window.isPost){ + // reLayout() + // } + + reHeightToc(); +}; + +// Nav switch function on mobile +/*****************************************************************************/ +const navToggle = document.getElementById('site-nav-toggle'); +navToggle.addEventListener('click', () => { + let aboutContent = document.getElementById('nav-content') + if (!aboutContent.classList.contains('show-block')) { + aboutContent.classList.add('show-block'); + aboutContent.classList.remove('hide-block') + } else { + aboutContent.classList.add('hide-block') + aboutContent.classList.remove('show-block'); + } +}) + + +// global search +/*****************************************************************************/ + +const searchButton = document.getElementById('search') +const searchField = document.getElementById('search-field') +const searchInput = document.getElementById('search-input') +const searchResultContainer = document.getElementById('search-result-container') +const escSearch = document.getElementById('esc-search') +const beginSearch = document.getElementById('begin-search') + +searchField.addEventListener('mousewheel',(e) => { + // e.preventDefault() + e.stopPropagation() + return false +}, false) + +var searchJson; +var caseSensitive = false + +searchButton.addEventListener('click', () => { + search() +}); + +escSearch.addEventListener('click',() => { + hideSearchField() +}) + +beginSearch.addEventListener('click',() => { + let keyword = searchInput.value; + if(keyword){ + searchFromKeyWord(keyword) + } +}) + +function toggleSeachField(){ + if (!searchField.classList.contains('show-flex-fade')) { + showSearchField() + } else { + hideSearchField() + } +} + +function showSearchField() { + searchInput.focus() + searchField.classList.add('show-flex-fade'); + searchField.classList.remove('hide-flex-fade'); +} + +function hideSearchField(){ + window.onkeydown = null; + searchField.classList.add('hide-flex-fade'); + searchField.classList.remove('show-flex-fade'); +} + +function searchFromKeyWord(keyword = ""){ + let result = []; + + let sildeWindowSize = 100; + + let handleKeyword = keyword + + if(!caseSensitive){ + handleKeyword = keyword.toLowerCase() + } + if(!searchJson) return -1; + else { + searchJson.forEach((item) => { + + if(!item.title || !item.content) return 0; // break + + let title = item.title + let content = item.content.trim().replace(/<[^>]+>/g,"").replace(/[`#\n]/g,""); + + let lowerTitle = title,lowerContent = content; + + if(!caseSensitive){ + lowerTitle = title.toLowerCase(); + lowerContent = content.toLowerCase(); + } + + + if(lowerTitle.indexOf(handleKeyword) !== -1 || lowerContent.indexOf(handleKeyword) !== -1){ + let resultItem = {} + resultItem.title = title.replace(keyword, "" + keyword + ''); + resultItem.url = item.url; + + resultItem.content = []; + + let lastend = 0 + + while(lowerContent.indexOf(handleKeyword) !== -1){ + let begin = lowerContent.indexOf(handleKeyword) - sildeWindowSize / 2 < 0 ? 0 : lowerContent.indexOf(handleKeyword) - sildeWindowSize / 2 + let end = begin + sildeWindowSize; + let reg = caseSensitive ? new RegExp('('+keyword+')','g') : new RegExp('('+keyword+')','ig') + resultItem.content.push("..." + content.slice(lastend + begin, lastend + end).replace(reg, "$1") + "...") + lowerContent = lowerContent.slice(end, lowerContent.length) + lastend = end + } + // resultItem.title = title.replace(keyword, "" + keyword + ''); + result.push(resultItem) + } + }) + } + + if(!result.length){ + searchResultContainer.innerHTML = ` +
No Result
+ ` + return; + } + + let searchFragment = document.createElement('ul') + + for(let item of result){ + let searchItem = document.createElement('li'); + let searchTitle = document.createElement('a'); + searchTitle.href = item.url + searchTitle.innerHTML = item.title; + searchItem.appendChild(searchTitle) + if(item.content.length) { + let searchContentLiContainer = document.createElement('ul') + for (let citem of item.content) { + let searchContentFragment = document.createElement('li') + searchContentFragment.innerHTML = citem; + searchContentLiContainer.appendChild(searchContentFragment) + } + searchItem.appendChild(searchContentLiContainer) + } + searchFragment.appendChild(searchItem) + } + while(searchResultContainer.firstChild){ + searchResultContainer.removeChild(searchResultContainer.firstChild) + } + searchResultContainer.appendChild(searchFragment) +} + +function search(){ + + toggleSeachField() + + window.onkeydown = (e) => { + if (e.which === 27) { + /** 这里编写当ESC按下时的处理逻辑! */ + toggleSeachField() + } else if(e.which === 13){ + // 回车按下 + let keyword = searchInput.value; + if(keyword){ + searchFromKeyWord(keyword) + } + } + } + + + if(!searchJson){ + let isXml; + let search_path = window.hexo_search_path; + if (search_path.length === 0) { + search_path = "search.json"; + } else if (/json$/i.test(search_path)) { + isXml = false; + } + let path = window.hexo_root+ search_path; + $.ajax({ + url: path, + dataType: isXml ? "xml" : "json", + async: true, + success: function (res) { + searchJson = isXml ? $("entry", res).map(function() { + return { + title: $("title", this).text(), + content: $("content",this).text(), + url: $("url" , this).text() + }; + }).get() : res; + } + }); + } + +} + +// directory function in post pages +/*****************************************************************************/ +function getDistanceOfLeft(obj) { + let left = 0; + let top = 0; + while (obj) { + left += obj.offsetLeft; + top += obj.offsetTop; + obj = obj.offsetParent; + } + return { + left:left, + top:top + }; +} + +var toc = document.getElementById('toc') + +var tocToTop = getDistanceOfLeft(toc).top; + +function reHeightToc(){ + if(toc) { // resize toc height + toc.style.height = ( document.documentElement.clientHeight - 10 ) + 'px'; + toc.style.overflowY = 'scroll'; + } +} + +reHeightToc(); + +if(window.isPost){ + var result = [] + + var nameSet = new Set(); + + if(!toc || !toc.children || !toc.children[0]){ + // do nothing + } + else { + if (toc.children[0].nodeName === "OL") { + let ol = Array.from(toc.children[0].children) + + function getArrayFromOl(ol) { + let result = [] + + // let escape = function (item) { + // return item.replace(/<[^>]+>/g, "").replace(/^\s\s*/, '').replace(/\s\s*$/, '').replace(/[\. _]/g, '-') + // } + + ol.forEach((item) => { + if (item.children.length === 1) { + // TODO: need change + let value = item.children[0].getAttribute('href').replace(/^#/,"") + result.push({ + value: [value], + dom: item + }) + nameSet.add(value) + } + else { + let concatArray = getArrayFromOl(Array.from(item.children[1].children)) + nameSet.add(item.children[0].getAttribute('href').replace(/^#/,"")) + result.push({ + value: [item.children[0].getAttribute('href').replace(/^#/,"")].concat(concatArray.reduce((p, n) => { + p = p.concat(n.value) + return p; + }, [])), + dom: item + }) + result = result.concat(concatArray) + } + }) + return result + } + + result = getArrayFromOl(ol) + } + + var nameArray = Array.from(nameSet) + + function reLayout() { + let scrollToTop = document.documentElement.scrollTop || window.pageYOffset // Safari is special + if(tocToTop === 0) { + // Fix bug that when resize window the toc layout may be wrong + toc = document.getElementById('toc') + toc.classList.remove('toc-fixed') + tocToTop = getDistanceOfLeft(toc).top; + } + if (tocToTop <= scrollToTop + 10) { + if (!toc.classList.contains('toc-fixed')) + toc.classList.add('toc-fixed') + } else { + if (toc.classList.contains('toc-fixed')) + toc.classList.remove('toc-fixed') + } + + let minTop = 9999; + let minTopsValue = "" + + for (let item of nameArray) { + let dom = document.getElementById(item) || document.getElementById(item.replace(/\s/g, '')) + if (!dom) continue + let toTop = getDistanceOfLeft(dom).top - scrollToTop; + + if (Math.abs(toTop) < minTop) { + minTop = Math.abs(toTop) + minTopsValue = item + } + + // console.log(minTopsValue, minTop) + } + + if (minTopsValue) { + for (let item of result) { + if (item.value.indexOf(minTopsValue) !== -1) { + item.dom.classList.add("active") + } else { + item.dom.classList.remove("active") + } + } + } + } + + reLayout() + + window.addEventListener('scroll', (e) => { + reLayout() + }) + } +} + diff --git a/links/index.html b/links/index.html index e69de29..251f512 100644 --- a/links/index.html +++ b/links/index.html @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + 常用链接 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 常用链接 +
+ + +
+

uweb浏览器中长按链接按钮可弹出常用链接菜单,这些链接定义在文件”default.links”中。每行格式如下:
[菜单名]:[url][空格][javascript脚本]
其中空格及之后的脚本为可选项。url及之后的脚本支持“%u”,”%s”等替换
脚本将在链接访问结束时自动执行。

+

url除支持所有标准的http(s):,javascript:等链接外,还支持超微内部链接(”:”为链接第二个字符)及特殊链接(”:”为链接首字符)。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/loadbt/index.html b/loadbt/index.html index e69de29..6b7bc6a 100644 --- a/loadbt/index.html +++ b/loadbt/index.html @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + 利用国外离线网盘囤积资源 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用国外离线网盘囤积资源 +
+ + +
+

百度网盘存储空间大,还支持离线下载。但其离线下载限制很多,可能由于某些重要节点被屏蔽的原因,下载国外资料基本都会失败。国外离线网盘空间小,但下载成功率很高。
本文介绍一种技术,使用国外离线网盘下载资源,然后一键离线至百度网盘。

+
    +
  • 注册国外离线网盘账号
  • +
  • 超微浏览器上配置百度离线下载

    +
      +
    • 安装uweb定制Termux应用
    • +
    • 更新Termux, Termux执行如下命令:
      echo "deb [trusted=yes] http://termux.iikira.com stable main" >>/data/data/com.termux/files/usr/etc/apt/sources.list
      +apt update
      +apt upgrade
      +apt install baidupcs-go
      +
    • +
    • 登录百度网盘, Termux执行如下命令:
      BaiduPCS-Go login
      +BaiduPCS-Go config set -appid=266719
      +
    • +
    • /sdcard/uweb/default.longclick配置如下:
      百度离线下载:termux/*:/data/data/com.termux/files/usr/bin/BaiduPCS-Go od add
    • +
    • 重启超微浏览器,此时长按链接将会出现菜单“百度离线下载”。
    • +
    • (其它安装方法)用户亦可直接下载BaiduPCS-Go至termux目录/data/data/com.termux/files/usr/bin.
        +
      • 安卓手机请选择arm64版本。
      • +
      • 解压,Termux运行以下命令
        unzip /sdcard/Download/BaiduPCS-Go-v3.5.6-android-21-arm64.zip
      • +
      • 移动解压后文件至最终目的地。Termux运行以下命令
        mv BaiduPCS-Go /data/data/com.termux/files/usr/bin/.
      • +
      • 配置/sdcard/uweb/default.longclick如下:
        百度离线下载:termux/*:/data/data/com.termux/files/usr/bin/BaiduPCS-Go od add
      • +
      • 重启超微浏览器,长按链接运行百度离线下载,发现百度网盘还没登录。本步骤会将BaiduPCS-Go设置为可运行程序。
      • +
      • termux下执行”BaiduPCS-Go login”登录百度网盘。再次长按链接完美运行百度离线下载。
      • +
      +
    • +
    +
  • +
  • 离线下载资源至国外网盘,下载完成后在超微浏览器内点击资源下载,弹出菜单选择“百度离线下载”,完成整个流程。

    +
  • +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/logcat/index.html b/logcat/index.html index e69de29..c5dcc48 100644 --- a/logcat/index.html +++ b/logcat/index.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + 安卓系统出错诊断 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 安卓系统出错诊断 +
+ + +
+

超微浏览器如果闪退,会生成出错文件”/sdcard/uweb/error.log”。

+

如果超微或安卓系统或任何应用出现问题,则可利用超微浏览器进行诊断,方法如下:

+
    +
  • 访问常用命令网页,点击安装logcat相关的两个命令。
  • +
  • 清空后台并重启超微浏览器。
  • +
  • 长按历史按钮,执行命令”清空logcat”。
  • +
  • 触发有问题的功能。
  • +
  • 长按历史按钮,执行命令”输出logcat.log”.
  • +
  • 检查文件”/sdcard/uweb/logcat.log”内容。
  • +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/multiaccount/index.html b/multiaccount/index.html index e69de29..24f924f 100644 --- a/multiaccount/index.html +++ b/multiaccount/index.html @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + 利用多账号登录获取资源 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 利用多账号登录获取资源 +
+ + +
+

谈到资源就离不开bt, bt下载费时费力,离线bt是最佳选择。国内离线下载由于关键节点屏蔽,基本没啥用。我的个人体验是彻彻底底完全没用,但别人也许还有点用?国外唯一一个有好体验的是seedr, 不过seedr有个大问题需要解决。

+

其它我曾推荐过的台湾bt, bug实在太多,现在看来也成了半个垃圾。万般无奈之下只能重拾seedr.

+

seedr的问题是首次登录需要google人机验证,登录成功以后可以永久使用,无需小飞机辅助。

+

以前偶尔飞飞一点问题也没有,毕竟1分钟飞行就可解决很长时间问题了。但目前的状态是信息基本被彻底封死,1分钟飞行也成了奢望。所以十分有必要珍惜这来之不易的1分钟飞行成果。

+

现在直接上方案,使用超微浏览器多账号登录。飞行1分钟以后成功登录seedr, 此时退出浏览器,千万不能强退,一定要让运存中的登录信息写到内部存储。然后用户可备份应用内部目录下的.cjar文件,一旦浏览器失去登录状态,可恢复此文件,即可使用多账号登录重新登录,让这1分钟飞行成果保存下来,供万万年使用。需要注意的一点是:用户退出seedr账号会使保存的文件作废。故千万不要退出账号,需要用其它账号登录的请使用多账号登录。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/offlinecache/index.html b/offlinecache/index.html index e69de29..bab1a3a 100644 --- a/offlinecache/index.html +++ b/offlinecache/index.html @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + 装载网站离线资源 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 装载网站离线资源 +
+ + +
+

uweb浏览器支持装载网站离线资源。只需要将离线资源存为文件”/sdcard/uweb/sitecache/[域名]/[全部路径,包括文件名,?,&,=, 与url一模一样]”。如果应用内部目录有文件夹”sitejs”存在,则“/sdcard/uweb”下的离线资源不再生效,此时生效离线资源为内部目录下的”sitecache”文件夹。

+

打开选项以后超微将自动装载这些离线资源。

+

离线资源可作为缓存提高浏览器性能; 可作为国外网站部分备份修复服务访问; 也可替换部分网站资源达到定制网站的作用。

+

下面以google翻译为例说明如何发现并备份离线资源。

+
    +
  • 首先使用教程”运行远程javascript“配置google翻译。
  • +
  • 将文件”/sdcard/uweb/types.sniff”内容清空(不要删除文件,否则会恢复成默认文件)。重启浏览器以后长按设置打开资源嗅探。
  • +
  • 准备好合适手段保证google系网站能正常访问,长按按钮在主屏运行google翻译。
  • +
  • 出现google翻译工具条以后,长按设置关闭嗅探。
  • +
  • 运行termux,安装下载工具wget:
    apt update;apt install wget
  • +
  • 下载必要离线数据,termux下运行如下命令:
    cd /sdcard/uweb
    +mkdir sitecache
    +cd sitecache
    +wget -U 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)' -x -i ../sniff.log
  • +
  • 下载结束后,离线资源就准备妥当,供以后随时使用。
  • +
  • google翻译的情况下,要对部分js作修改,防止每次访问url不同。
  • +
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/pccopy/index.html b/pccopy/index.html index e69de29..98a64cd 100644 --- a/pccopy/index.html +++ b/pccopy/index.html @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + 笔记及手机复制(富)文本至PC剪贴板 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 笔记及手机复制(富)文本至PC剪贴板 +
+ + +
+

技巧等级:笔记(中级) PC剪贴板(高级)

+

手机需安装uweb定制Termux。如使用剪贴板功能,termux还需安装openssl。

+

配置/sdcard/uweb/default.select如下:

+
笔记::(cat;echo;echo;)>>notes.txt
+富文本笔记:html:(cat;echo '<p></p>';echo;)>>notes.html
+命名笔记:(cat;echo;echo;)>>%s
+复制至PC剪贴板::ssh [user:password]@192.168.2.102 "DISPLAY=:0 xsel -i"
+复制富文本至PC剪贴板:html:ssh [user:password]@192.168.2.102 "DISPLAY=:0 xsel -i"
+ +

此处假定远程PC的IP地址为192.168.2.102,PC已经开通了ssh服务。建议用户配置ssh服务为免密码登录,此时用户无需将密码写入文件default.select。用户PC上安装有xsel剪贴板工具。使用其它工具请酌情修改。

+

重启浏览器,长按“书签”按钮,将弹出菜单。若用户当前窗口并无选中文本,则选取整个页面作相应操作,否则以选中文本为准。

+

采用以上配置,笔记将储存在/sdcard/uweb目录下文件note.txt或note.html中(富文本)。命名笔记储存文件则由用户在地址栏输入框内指定。

+

手机其它应用中的文本可选中后分享给超微浏览器,再由超微浏览器作笔记或进一步分享给PC。如果其它应用无法分享选中文本,这种情况可以先复制文本至剪贴板。
在超微浏览器中长按并在新窗口打开此链接,然后点击窗口并粘贴文本。长按书签按钮选择适当功能即可复制至PC剪贴板。

+

通过新窗口打开上述链接,超微浏览器因此亦可用作简单的文本/html编辑器。用户可通过“命名笔记”存为地址栏输入框指定文件。

+

Windows PC

对Windows PC而言,vista及以后自带clip.exe,此时配置如下:
复制文本至PC剪贴板::ssh [user:password]@192.168.2.102 clip.exe

+

其它推荐工具(读取PC剪贴板):
pclip

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/pcdown/index.html b/pcdown/index.html index e69de29..b782cb6 100644 --- a/pcdown/index.html +++ b/pcdown/index.html @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + 浏览器一键控制台式机/服务器下载资源 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 浏览器一键控制台式机/服务器下载资源 +
+ + +
+

技巧等级:高级

+

小孩要听英文有声书“The lying games”,国内服务器没一个能下的,最后还是在手机上用seedr秒下。但seedr的登录要用google人机交互确认,用过代理、tunnel至手机等方法,台式机死活登录不上。下面言归正传,讲一下超微浏览器直接下载资源至台式机的方法:

+

手机需安装uweb定制Termux,并在termux下安装openssl,在Termux窗口下依次敲入如下命令:
apt update
apt upgrade
apt install openssl

+

脚本pcdownload内容如下(可放置在任意应用内部目录下,并相应修改default.longclick配置中文件路径):
#!/data/data/com.termux/files/usr/bin/sh
ssh [user:password]@192.168.2.102 "DISPLAY=:0 firefox \"$1\""

+

脚本需设置为可执行,Termux下执行命令:
chmod 755 /data/data/com.termux/files/usr/bin/pcdownload

+

这里假定用户已经在台式机上设好ssh服务,台式机IP地址为192.168.2.102,准备用firefox下载。如果下载工具不是图形程序,则上述脚本中可删去“DISPLAY=:0”。

+

配置文件/sdcard/uweb/default.longclick如下:
PCdown:/data/data/com.termux/files/usr/bin/pcdownload

+

重启超微浏览器,点击链接下载时会弹出菜单,选择”PCdown”,台式机会启动firefox下载手机指定文档。

+

可能大家有疑问,台式机无法登录,为什么手机可以登录?这是因为手机上应用多哈。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/redirect/index.html b/redirect/index.html index e69de29..d23ca4d 100644 --- a/redirect/index.html +++ b/redirect/index.html @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + 重定向国外网址至国内镜像(附编辑本地文件) + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 重定向国外网址至国内镜像(附编辑本地文件) +
+ + +
+

使用服务器在国外的搜索引擎体验往往不如国内的引擎。由于网站屏蔽的原因,两者之间索引权重差别很大。国外受欢迎的技术类网站因此难以在百度上搜到;国外引擎能搜到但由于其中不少结果无法访问而体验糟糕。

+

其实,很多技术类网站在国内早有镜像,但由于镜像并非众所周知,其索引权重在百度上微不足道,非专门搜索不可得。

+

本文介绍一种技术,可重定向国外网址至国内镜像,极大的提高国外引擎的体验,让更多用户更客观的理解全球技术。

+

配置/sdcard/uweb/default.redirect:
文件每一行格式为:
域名:正则表达式:替换表达式

+

其中正则表达式以java语言规定为准,表达式中不能包含’:’。正则表达式为空时系统默认为与域名相同。

+

例子文件内容如下:
developer.android.com::developer.android.google.cn

+

四种使用重定向的方法:

+
    +
  • 长按链接
    添加文件”国内镜像.js”至”/sdcard/uweb/longclick”目录下。
    文件内容如下:

    +
    //e:%u
    + +

    其中”e:”为uweb特殊url协议,意为”edit”,即”编辑”。当后面紧跟url网址的情况下会重定向网址。

    +

    重启uweb后长按链接弹出菜单选”国内镜像”,浏览器将访问网址的国内镜像。若网址为本地文件,则浏览器会自动调用此类文件编辑器。

    +
  • +
  • 长按工具条图像按钮

    +
  • +
  • 长按设置,选中”自定义重定向”。
  • +
  • 长按设置,选中”自定义资源重定向”。此选项除访问url重定向之外,还可重定向网页中一切资源。
  • +
+

更多重定向网址:
www.bilibili.com::www.ibilibili.com
pan.baidu.com::pan.baiduwp.com
www.docin.com::www.docin365.com
wenku.baidu.com::wenku.baiduvvv.com
detail.tmall.com::detail.tmallvvv.com
detail.m.tmall.com::detail.m.tmallvvv.com
item.taobao.com::item.taobaovvv.com
h5.m.taobao.com::h5.m.taobaovvv.com
jd.com::jdvvv.com
item.yhd.com::item.yhdvvv.com
goods.kaola.com::goods.kaolavvv.com
product.dangdang.com::product.dangdangvvv.com
item.gome.com.cn::item.gomevvv.com.cn

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/rjs/index.html b/rjs/index.html index e69de29..bc8fd41 100644 --- a/rjs/index.html +++ b/rjs/index.html @@ -0,0 +1,176 @@ + + + + + + + + + + + + + + 运行javascript脚本 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 运行javascript脚本 +
+ + +
+

uweb浏览器支持运行本地及远程javascript脚本。
大型脚本可安装到”/sdcard/uweb/bookmarklet”目录下:
彩云小译

+

远程及小型脚本可安装到default.rjs文件中:
点击安装站内搜索、背景图、新窗口打开链接、移除覆盖物等

+

远程脚本配置文件/sdcard/uweb/default.rjs示例如下:

+
彩云小译:'https://caiyunapp.com/dest/trs.js'
+移除覆盖物:'https://jamesfengcao.gitee.io/uweb/searchurl/bml/content/rmo.js'
+新窗口打开链接:'';{d=document,b=d.createElement('base');b.setAttribute('target','_blank');d.head.appendChild(b);}
+google translate:'https://translate.google.cn/translate_a/element.js?cb=googleTranslateElementInit';b=d.body;v=d.createElement('div');v.id='google_translate_element';v.style.display='none';b.insertBefore(v,b.firstChild);p=d.createElement('script');p.text="function googleTranslateElementInit(){new google.translate.TranslateElement({pageLanguage: 'auto',includedLanguages:'zh-CN,zh-TW,en'},'google_translate_element');}";p.type='text/javascript';b.appendChild(p)
+
+ +

default.rjs每行格式如下 (url部分支持js代码运算):
[远程脚本名]:[返回字符串的javascript代码]

+

重启浏览器,长按搜索按钮,则弹出远程脚本菜单。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/searchcat/index.html b/searchcat/index.html index e69de29..dcb482f 100644 --- a/searchcat/index.html +++ b/searchcat/index.html @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + 分类多引擎搜索 + + + + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + +
+
+
+ + + search +
+
+ +
+
+
+
+ +
+
+ +
+ + + + +
+
+ 分类多引擎搜索 +
+ + +
+

长按下面链接可直接下载为分类多引擎搜索配置文件,点击本链接自动安装所有文件至”/sdcard/uweb/bookmark”目录下
影视搜索
小说搜索

+

超微浏览器中通过“设置”->“总目录”->“↑”->“Download”,点击后缀为.search的下载文件,超微浏览器将自动显示分类多引擎搜索。此时可按菜单键(或长按底部工具条后退按钮)选择“添加到桌面”方便以后访问。

+

.search文件每行格式为如下几种:
[搜索引擎名]:[不含%s的url]
[搜索引擎名]:[含%s的url]
[搜索引擎名]:POST:[含%s的post参数]:[url]

+

.search文件首行必须为第一种类型的搜索引擎。由于其它两种类型的引擎数量稀少,为性能考虑,超微限制了首个引擎的种类。

+

本地引擎

搜索引擎已经支持命令行url,现在可添加离线字典查询至主页。命令行url格式为
c:[含%s的命令行]
d:mimetype:[含%s的命令行]:[外部资源url]
查询时关键词会自动替换命令行中的%s。

+

笔者用来查询各式词典,发现效果非常好。百兆以内的文本文件压缩以后可以直接快速检索,定位至特定位置以后可上下滚动阅读全部文本。

+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
    + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + diff --git a/searchurl/alipay.png b/searchurl/alipay.png index e69de29..83fb152 100644 Binary files a/searchurl/alipay.png and b/searchurl/alipay.png differ diff --git a/searchurl/backup.html b/searchurl/backup.html index e69de29..2c8602d 100644 --- a/searchurl/backup.html +++ b/searchurl/backup.html @@ -0,0 +1,34 @@ + + +备份与恢复 +

支持安卓6+。

+ +

备份目录"/sdcard/uweb"至坚果云 恢复

+ +

备份Cookie至坚果云(webview 76+,注意账号信息泄露危险) 恢复

+ +

设置坚果云用户及密码

+
+ +用户可将下列表格提交后访问的网址设为书签,方便以后再次备份恢复。
+
+
+
+
+ +
+ +

坚果云 易云
+uweb目录 +Cookie (webview 76+) +

+ + diff --git a/searchurl/bml/content/comparecells.js b/searchurl/bml/content/comparecells.js index e69de29..a8fe372 100644 --- a/searchurl/bml/content/comparecells.js +++ b/searchurl/bml/content/comparecells.js @@ -0,0 +1,197 @@ +/** + * Try to color the cells of comparison tables based on their contents. + * + * @title Compare cells + */ +(function comparecells() { + /* Create a new IFRAME to get a "clean" Window object, so we can use its + * console. Sometimes sites (e.g. Twitter) override console.log and even + * the entire console object. "delete console.log" or "delete console" + * does not always work, and messing with the prototype seemed more + * brittle than this. */ + let console = (function () { + let iframe = document.getElementById('xxxJanConsole'); + if (!iframe) { + iframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe'); + iframe.id = 'xxxJanConsole'; + iframe.style.display = 'none'; + + (document.body || document.documentElement).appendChild(iframe); + } + + return iframe && iframe.contentWindow && iframe.contentWindow.console || { + log: function () {} + }; + })(); + + /** + * Get the text content for the given element. + */ + function getTextFromElement(element) { + /* TODO: take IMG@alt, BUTTON@value etc. into account */ + return element.textContent.trim().toLowerCase(); + } + + /** + * Get a Uint8Array of the SHA-256 bytes for the given string. + */ + async function getSha256Bytes(string) { + try { + if ( + typeof crypto === 'object' && typeof crypto.subtle === 'object' && typeof crypto.subtle.digest === 'function' + && typeof Uint8Array === 'function' + && typeof TextEncoder === 'function' + ) { + return new Uint8Array(await crypto.subtle.digest('SHA-256', new TextEncoder('utf-8').encode(string))); + } + } catch (e) { + return null; + } + } + + async function getColorsForValue(value) { + /* Cache the calculated values. */ + getColorsForValue.cellValuesToRgb = getColorsForValue.cellValuesToRgb || {}; + + if (!getColorsForValue.cellValuesToRgb[value]) { + let normalizedValue = value.trim().toLowerCase(); + let hash; + + let yesValues = [ + '✔', + 'yes', + 'ja', + 'oui', + 'si', + 'sí' + ]; + + let noValues = [ + 'x', + 'no', + 'nee', + 'neen', + 'nein', + 'non', + 'no' + ]; + + if (yesValues.indexOf(normalizedValue) > -1) { + /* Make "Yes" cells green. */ + getColorsForValue.cellValuesToRgb[value] = [ 150, 255, 32 ]; + } else if (noValues.indexOf(normalizedValue) > -1) { + /* Make "No" cells green. */ + getColorsForValue.cellValuesToRgb[value] = [ 238, 32, 32 ]; + } else if ((shaBytes = await getSha256Bytes(normalizedValue))) { + /* Give other cells a color based on their content’s SHA + * hash to ensure “consistent random colors” every time. */ + getColorsForValue.cellValuesToRgb[value] = [ + shaBytes[0], + shaBytes[1], + shaBytes[2] + ]; + } else { + /* If the SHA hash could not be calculated, just use random + * values. These will change on every execution. */ + getColorsForValue.cellValuesToRgb[value] = [ + Math.random() * 255, + Math.random() * 255, + Math.random() * 255 + ]; + } + } + + /* Calculate/approximate the lightness (tweaked from “RGB to HSL”) to + * determine whether black or white text is best suited. */ + let isLight = 150 < ( + getColorsForValue.cellValuesToRgb[value][0] * 0.299 + + getColorsForValue.cellValuesToRgb[value][1] * 0.587 + + getColorsForValue.cellValuesToRgb[value][2] * 0.114 + ); + + return { + backgroundColor: 'rgb(' + getColorsForValue.cellValuesToRgb[value].join(', ') + ')', + color: isLight + ? 'black' + : 'white', + textShadow: isLight + ? '1px 1px 3px white' + : '1px 1px 3px black' + }; + } + + /* The main function. */ + (function execute(document) { + Array.from(document.querySelectorAll('table')).forEach(table => { + Array.from(table.tBodies).forEach(tBody => { + if (tBody.rows.length < 3) { + console.log('Compare cells: skipping table body ', tBody, ' because it only has ', tBody.rows.length, ' rows'); + return; + } + + Array.from(tBody.rows).forEach(tr => { + /* Determine the values. */ + let cellValues = []; + let uniqueCellValues = new Set(); + + Array.from(tr.cells).forEach((cell, i) => { + /* Don't take the header cells into account. */ + if (cell.tagName.toUpperCase() === 'TH') { + return; + } + + /* Assume the first cell is a header cell, even if it is not a TH. */ + if (i === 0) { + return; + } + + cellValues[i] = getTextFromElement(cell); + uniqueCellValues.add(cellValues[i]); + }); + + /* Color (or not) the cells based on the values. */ + let isFirstValue = true; + let firstValue; + cellValues.forEach(async function(cellValue, i) { + let hasTwoUniqueValues = uniqueCellValues.size == 2; + if (isFirstValue) { + firstValue = cellValue; + isFirstValue = false; + } + + let backgroundColor; + let color; + let textShadow; + + if ( + uniqueCellValues.size == 1 || + (hasTwoUniqueValues && cellValue === firstValue) || + cellValue.trim() === '' + ) { + backgroundColor = 'inherit'; + color = 'inherit'; + textShadow = 'inherit'; + } else { + backgroundColor = (await getColorsForValue(cellValue)).backgroundColor; + color = (await getColorsForValue(cellValue)).color; + textShadow = (await getColorsForValue(cellValue)).textShadow; + } + + tr.cells[i].style.setProperty('background-color', backgroundColor, 'important'); + tr.cells[i].style.setProperty('color', color, 'important'); + tr.cells[i].style.setProperty('text-shadow', textShadow, 'important'); + }); + }); + }); + }); + + /* Recurse for frames and iframes. */ + try { + Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) { + execute(elem.contentDocument); + }); + } catch (e) { + /* Catch exceptions for out-of-domain access, but do not do anything with them. */ + } + })(document); +})(); diff --git a/searchurl/bml/content/designmode.js b/searchurl/bml/content/designmode.js index e69de29..1a4a3b9 100644 --- a/searchurl/bml/content/designmode.js +++ b/searchurl/bml/content/designmode.js @@ -0,0 +1 @@ +(function(){if (document.designMode == 'off'){document.designMode = 'on';}else{document.designMode = 'off';}})() diff --git a/searchurl/bml/content/freeviddy.js b/searchurl/bml/content/freeviddy.js index e69de29..2393588 100644 --- a/searchurl/bml/content/freeviddy.js +++ b/searchurl/bml/content/freeviddy.js @@ -0,0 +1,54 @@ +/** + * Free the VIDEO elements: get rid of overlays, and enable the native controls. + * + * Useful on https://www.instagram.com/ where the stupid overlays prevent + * showing the controls and triggering the context menu, so you don’t know how + * long the video will take and can't play the video in full screen mode. + * + * @title Free Viddy + */ +(function freeviddy() { + /* Recursively execute the main logic on the document and its sub-documents. */ + function execute(document) { + document.addEventListener('touchmove mousemove', function debouncer(event) { + clearTimeout(debouncer.timeoutId); + debouncer.timeoutId = setTimeout(function () { + let elementsUnderPointer = document.elementsFromPoint(event.clientX, event.clientY); + let overlaysToRemove = []; + + for (let i = 0; i < elementsUnderPointer.length; i++) { + if ((elementsUnderPointer[i].tagName.toUpperCase() === 'VIDEO' || + elementsUnderPointer[i].tagName.toUpperCase() === 'IFRAME') && !elementsUnderPointer[i].xxxJanFreeViddyProcessed) { + let video = elementsUnderPointer[i]; + video.controls = true; + video.xxxJanFreeViddyProcessed = true; + + if (i === 0) { + } else { + overlaysToRemove = elementsUnderPointer.slice(0, i); + } + + break; + } + } + + if (overlaysToRemove.length) { + overlaysToRemove.forEach(element => element.remove()); + } + }, 50); + }); + + /* Recurse for frames and iframes. */ + try { + Array.from( + document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]') + ).forEach( + elem => execute(elem.contentDocument) + ); + } catch (e) { + /* Catch exceptions for out-of-domain access, but do not do anything with them. */ + } + } + + execute(document); +})(); diff --git a/searchurl/bml/content/fullimg.js b/searchurl/bml/content/fullimg.js index e69de29..649b492 100644 --- a/searchurl/bml/content/fullimg.js +++ b/searchurl/bml/content/fullimg.js @@ -0,0 +1,497 @@ +/** + * Load the full-size versions of resized images based on their "src" + * attribute, or their containing link's "href" attribute. Also, make IFRAMEs + * take up the entire width of their offset parent (useful for embedded videos + * and whatnot). Same goes for the VIDEO elements. + * + * @title Load full images + */ +(function fullimg() { + /* Create a new IFRAME to get a "clean" Window object, so we can use its + * console. Sometimes sites (e.g. Twitter) override console.log and even + * the entire console object. "delete console.log" or "delete console" + * does not always work, and messing with the prototype seemed more + * brittle than this. */ + var console = (function () { + var iframe = document.getElementById('xxxJanConsole'); + if (!iframe) { + iframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe'); + iframe.id = 'xxxJanConsole'; + iframe.style.display = 'none'; + + (document.body || document.documentElement).appendChild(iframe); + } + + return iframe && iframe.contentWindow && iframe.contentWindow.console || { + log: function () {} + }; + })(); + + /* Get rid of "width=", "height=" etc. followed by numbers or number pairs + * in IMG@src query strings. */ + var parameterNames = [ + 'width', + 'Width', + + 'height', + 'Height', + + 'maxwidth', + 'maxWidth', + 'MaxWidth', + + 'maxheight', + 'maxHeight', + 'MaxHeight', + + 'w', + 'W', + + 'h', + 'H', + + 'fit', + 'Fit', + + 'resize', + 'reSize', + 'Resize', + + 'size', + 'Size' + ]; + + parameterNames.forEach(function (parameterName) { + var selector = 'img[src*="?' + parameterName + '="]' + + ', img[src*="?"][src*="&' + parameterName + '="]'; + + /* Match query string parameters (?[…&]name=value[&…]) where the value is + * a number (e.g. "width=1200") or a pair of numbers (e.g. * "resize=640x480"). */ + var parameterReplacementRegexp = new RegExp('(\\?[^#]*&)?' + parameterName + '=[1-9][0-9]+(?:(?:[xX,*:]|%2[CcAa]|%3[Aa])[1-9][0-9]+)?([^&#]*)'); + + [].forEach.call(document.querySelectorAll(selector), function (img) { + var newSrc = img.src + /* Remove the parameter "name=value" pair from the query string. */ + .replace(parameterReplacementRegexp, '$1$2') + + /* Remove trailing "&" from the query string. */ + .replace(/(\?[^#]*)&(#.*)?$/, '$1$2') + + /* Remove empty query strings ("?" not followed by + * anything) from the URL. */ + .replace(/\?(#.*)?$/, '$1') + + /* Remove empty fragment identifiers from the URL. */ + .replace(/#$/, '') + ; + + changeSrc(img, newSrc, 'found image with parameter "' + parameterName + '" in query string'); + }); + }); + + /* Show the original image for Polopoly CMS "generated derivatives". + * + * Example: + * https://sporza.be/polopoly_fs/1.2671026!image/1706320883.jpg_gen/derivatives/landscape670/1706320883.jpg + * https://sporza.be/polopoly_fs/1.2671026!image/1706320883.jpg + */ + [].forEach.call( + document.querySelectorAll('img[src*="_gen/derivatives/"]'), + function (img) { + var matches = img.src.match(/(.*\.(jpe?g|png|gif))_gen.*\.\2(\?.*)?$/); + if (matches && matches[1]) { + changeSrc(img, matches[1], 'found image with Polopoly CMS "generated derivative" URL'); + } + } + ); + + /* Try to load the originals for images whose source URLs look like + * thumbnail/resized versions with dimensions. + */ + [].forEach.call( + document.images, + function (img) { + var oldSrc = img.src; + /* Example: + * https://www.cycling-challenge.com/wp-content/uploads/2014/08/IMG_6197-150x150.jpg + * https://www.cycling-challenge.com/wp-content/uploads/2014/08/IMG_6197.jpg + */ + var matches = oldSrc.match(/(.*)[-_.@]\d+x\d+(\.[^\/.]+)/); + if (matches && matches[1] && matches[2]) { + var newSrc = matches[1] + matches[2]; + + return changeSrc(img, newSrc, 'found image whose URL looks like a thumbnail/resized version'); + } + + /* Example: + * https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Kowloon-Walled-City-1898.jpg/220px-Kowloon-Walled-City-1898.jpg + * https://upload.wikimedia.org/wikipedia/commons/8/83/Kowloon-Walled-City-1898.jpg + */ + matches = oldSrc.match(/(.*\/)thumb\/(.*)\/[^\/]+$/); + if (matches) { + var newSrc = matches[1] + matches[2]; + + return changeSrc(img, newSrc, 'found image whose URL looks like a MediaWiki thumbnail/resized version'); + } + + } + ); + + /* Try to load the originals for images whose source URLs look like + * thumbnail/resized versions with a text label. + * + * Example: + * https://www.crazyguyonabike.com/pics/docs/00/01/27/84/small/DSCF3555.JPG + * https://www.crazyguyonabike.com/pics/docs/00/01/27/84/large/DSCF3555.JPG + */ + var thumbnailPathRegexp = /(.*[/.-])(small|thumb|thumbnail|resized|preview|medium)([/.-].*)/; + + var fullSizePathParts = [ + 'large', + 'original', + 'source', + 'normal', + 'xlarge', + ]; + + [].forEach.call( + document.images, + function (img) { + var oldSrc = img.src; + var matches = oldSrc.match(thumbnailPathRegexp); + if (matches) { + var newSources = []; + + fullSizePathParts.forEach(function (part) { + newSources.push(matches[1] + part + matches[3]); + }); + + changeSrc(img, newSources, 'found image whose URL looks like a thumbnail/resized version'); + } + } + ); + + /* Change the IMG@src of linked images to their link's A@href if they look + * similar, assuming that the linked version is larger. */ + [].forEach.call( + document.querySelectorAll('a img'), + function (img) { + if (!img.src) { + return; + } + + var a = img.parentNode; + while (a && a.tagName && a.tagName.toLowerCase() !== 'a') { + a = a.parentNode; + } + + if (!a) { + return; + } + + var aHref = a.href; + + if (a.hostname.match(/\.blogspot\.com$/)) { + /* Get rid of Blogspot's links to useless HTML wrappers. */ + aHref = aHref.replace(/\/(s\d+)-h\/([^\/]+)$/, '/$1/$2'); + } + + if (aHref === img.src) { + return; + } + + /* Simplify a URL for similarity calculation. */ + function simplifyUrl(url) { + return ('' + url) + .replace(/\d+/g, '0') + .replace(/^https?:/, ''); + } + + var similarity = getSimilarity(simplifyUrl(img.src), simplifyUrl(a.href)); + + if (similarity > 0.66) { + changeSrc(img, aHref, 'found linked image with ' + Math.round(similarity * 100) + '% similarity'); + } + } + ); + + /* Change all Blogspot images that have not been changed yet. */ + Array.from( + document.querySelectorAll('img[src*="bp.blogspot.com/"]') + ).forEach(img => { + let matches; + if ((matches = img.src.match(/^(.*\/)s(\d+)(\/[^/]+)$/)) && matches[2] < 9999) { + let newSrc = matches[1] + 's9999' + matches[3]; + changeSrc(img, newSrc, 'found Blogspot image with restricted size (' + matches[2] + ')'); + } + }); + + /* Use larger YouTube thumbnails. */ + Array.from( + document.querySelectorAll('img[src*="//yt"][src*=".ggpht.com"]') + ).forEach(img => { + let matches; + if ((matches = img.src.match(/^(.*\/)s(\d+)([^/]+\/photo\.[^/.]+)$/)) && matches[2] < 1024) { + let newSrc = matches[1] + 's1024' + matches[3]; + changeSrc(img, newSrc, 'found YouTube avatar with restricted size (' + matches[2] + ')'); + } + }); + + /* Get rid of all IMG@srcset attributes that have not been removed in the + * previous steps. + */ + [].forEach.call( + document.querySelectorAll('img[srcset]'), + function (img) { + console.log('Load full images: removing srcset attribute: ', img); + + img.originalSrcset = img.getAttribute('srcset'); + img.removeAttribute('srcset'); + } + ); + + /* Make native VIDEO elements and video IFRAMEs take up the entire width + * of their offset parent. */ + var elementsToEnlargeSelectors = [ + 'video', + 'iframe.twitter-tweet-rendered', + 'iframe[src*="embed"]', + 'iframe[src*="video"]', + 'iframe[src*="syndication"]', + 'iframe[class*="altura"]', + 'iframe[id*="altura"]', + 'iframe[src*="altura"]', + 'iframe[src*="//e.infogr.am/"]', + 'iframe[src*="//www.kickstarter.com/projects/"]', + 'iframe[src*="//media-service.vara.nl/player.php"]', + 'iframe[src*="//player.vimeo.com/video/"]' + ]; + + [].forEach.call( + document.querySelectorAll(elementsToEnlargeSelectors.join(', ')), + function (element) { + var scale = element.offsetParent.offsetWidth / element.offsetWidth; + var newWidth = Math.round(element.offsetWidth * scale); + var newHeight = Math.round(element.offsetHeight * scale); + + console.log( + 'Load full images: resizing element ', element, + ' from ' + element.offsetWidth + 'x' + element.offsetHeight + + ' to ' + newWidth + 'x' + newHeight + ); + + element.xxxJanReadableAllowStyle = true; + element.style.width = newWidth + 'px'; + element.style.height = newHeight + 'px'; + } + ); + + /* Show controls on AUDIO and VIDEO elements. */ + [].forEach.call( + document.querySelectorAll('audio, video'), + function (element) { + element.controls = true; + } + ); + + /* Show controls on YouTube embeds. */ + [].forEach.call( + document.querySelectorAll('iframe[src^="https://www.youtube.com/embed/"][src*="?"][src*="=0"]'), + function (iframe) { + var beforeAndAfterHash = iframe.src.split('#'); + var beforeAndAfterQuery = beforeAndAfterHash[0].split('?'); + + + var newPrefix = beforeAndAfterQuery[0]; + + var newQueryString = ''; + if (beforeAndAfterQuery.length > 1) { + beforeAndAfterQuery.shift(); + + var newQueryParts = beforeAndAfterQuery + .join('?') + .split('&') + .filter(function (keyValuePair) { + return !keyValuePair.match(/^(controls|showinfo|rel)=0$/); + } + ); + + if (newQueryParts.length) { + newQueryString = '?' + newQueryParts.join('&'); + } + } + + var newHash = ''; + if (beforeAndAfterHash.length > 1) { + beforeAndAfterHash.shift(); + newHash = '#' + beforeAndAfterHash.join('#'); + } + + var newSrc = newPrefix + newQueryString + newHash; + + if (newSrc !== iframe.src) { + iframe.src = newSrc; + } + } + ); + + /** + * Crudely calculate the similarity between two strings. Taken from + * https://stackoverflow.com/a/10473855. An alternative would be the + * Levenshtein distance, implemented in JavaScript here: + * https://andrew.hedges.name/experiments/levenshtein/ + */ + function getSimilarity(strA, strB) { + var result = 0; + + var i = Math.min(strA.length, strB.length); + + if (i === 0) { + return; + } + + while (--i) { + if (strA[i] === strB[i]) { + continue; + } + + if (strA[i].toLowerCase() === strB[i].toLowerCase()) { + result++; + } else { + result += 4; + } + } + + return 1 - (result + 4 * Math.abs(strA.length - strB.length)) / (2 * (strA.length + strB.length)); + } + + /** + * Change the IMG@src and fall back to the original source if the new + * source triggers an error. You can specify an array of new sources that + * will be tried in order. When all of the new sources fail, the original + * source will be used. + */ + function changeSrc(img, newSrc, reason) + { + var basename = img.src.replace(/[?#].*/, '').replace(/.*?([^\/]*)\/*$/, '$1'); + + console.log('[' + basename + '] Load full images: ' + reason + ': ', img); + + if (img.hasNewSource) { + console.log('[' + basename + '] Image already has a new source: ', img); + return; + } + + var newSources = Array.isArray(newSrc) + ? newSrc + : [ newSrc ]; + + while ((newSrc = newSources.shift())) { + if (newSrc && img.src !== newSrc) { + break; + } + } + + if (!newSrc) { + return; + } + + console.log('[' + basename + '] → Old img.src: ' + img.src); + console.log('[' + basename + '] → Try img.src: ' + newSrc); + + /* Save the original source. */ + if (!img.originalSrc) { + img.originalSrc = img.src; + } + + if (!img.originalNaturalWidth) { + img.originalNaturalWidth = img.naturalWidth; + } + + if (!img.originalNaturalHeight) { + img.originalNaturalHeight = img.naturalHeight; + } + + /* Save and disable the srcset on the IMG element. */ + if (img.hasAttribute('srcset')) { + img.originalSrcset = img.getAttribute('srcset'); + img.removeAttribute('srcset'); + } + + /* Save and disable the srcset in the container PICTURE element's SOURCE descendants. */ + if (img.parentNode.tagName.toLowerCase() === 'picture') { + [].forEach.call( + img.parentNode.querySelectorAll('source[srcset]'), + function (source) { + source.originalSrcset = source.getAttribute('srcset'); + source.removeAttribute('srcset'); + } + ); + } + + /* When the new source has failed to load, load the next one from the + * list of possible new sources. If there are no more left, revert to + * the original source. */ + var errorHandler; + + if (newSources.length) { + console.log('[' + basename + '] Setting errorHandler to loadNextNewSrc for ', img, '; newSources: "' + newSources.join('", "') + '"; reason:', reason); + errorHandler = function loadNextNewSrc() { + img.removeEventListener('error', loadNextNewSrc); + changeSrc(img, newSources, reason); + }; + } else { + console.log('[' + basename + '] Setting errorHandler to restoreOriginalSrc for ', img, '; originalSrc: "' + img.originalSrc + '"; reason:', reason); + errorHandler = function restoreOriginalSrc() { + console.log('[' + basename + '] Load full images: error while loading new source for image: ', img); + console.log('[' + basename + '] → Unable to load new img.src: ' + newSrc); + console.log('[' + basename + '] → Resetting to original img.src: ' + img.originalSrc); + + img.removeEventListener('error', restoreOriginalSrc); + + /* Restore the original source. */ + img.src = img.originalSrc; + + /* Re-enable the original srcset on the IMG element. */ + if (img.originalSrcset) { + img.setAttribute('srcset', img.originalSrcset); + delete img.originalSrcset; + } + + /* Re-enable the original srcset in the container PICTURE element's SOURCE descendants. */ + if (img.parentNode.tagName.toLowerCase() === 'picture') { + [].forEach.call( + img.parentNode.querySelectorAll('source'), + function (source) { + if (source.originalSrcset) { + source.setAttribute('srcset', source.originalSrcset); + delete source.originalSrcset; + } + } + ); + } + + }; + } + + img.addEventListener('error', errorHandler); + + /* When the new source image is smaller than the original image, + * treat that as an error, too. */ + img.addEventListener('load', function () { + if (img.naturalWidth * img.naturalHeight < img.originalNaturalWidth * img.originalNaturalHeight) { + console.log('[' + basename + '] Load full images: new image (', img.naturalWidth, 'x', img.naturalHeight, ') is smaller than old image (', img.originalNaturalWidth, 'x', img.originalNaturalHeight, '): ', img); + + return errorHandler(); + } + + if (img.src !== img.originalSrc) { + console.log('[' + basename + '] → Success: ' + img.src); + img.hasNewSource = true; + } + }); + + /* Finally, actually try to load the image. */ + img.src = newSrc; + } +})(); diff --git a/searchurl/bml/content/read.js b/searchurl/bml/content/read.js index e69de29..ba578fb 100644 --- a/searchurl/bml/content/read.js +++ b/searchurl/bml/content/read.js @@ -0,0 +1,1447 @@ +/** + * Make a page more readable by disabling all page styling and applying a + * bare minimum of our own. Go to the first thing that looks like the start + * of the actual content so no time is wasted scrolling past initial + * navigation etc. + * + * @title Readable++ + */ +(function read() { + /* Create a new IFRAME to get a "clean" Window object, so we can use its + * console. Sometimes sites (e.g. Twitter) override console.log and even + * the entire console object. "delete console.log" or "delete console" + * does not always work, and messing with the prototype seemed more + * brittle than this. */ + var console = (function () { + var iframe = document.getElementById('xxxJanConsole'); + if (!iframe) { + iframe = document.createElementNS('http://www.w3.org/1999/xhtml', 'iframe'); + iframe.id = 'xxxJanConsole'; + iframe.style.display = 'none'; + + (document.body || document.documentElement).appendChild(iframe); + } + + return iframe && iframe.contentWindow && iframe.contentWindow.console || { + log: function () {} + }; + })(); + + /* The style sheet for more readable content. */ + var css = (function () { /*@charset "utf-8"; + @namespace svg "http://www.w3.org/2000/svg"; + + -jancss-comment { content: + "General styles -------------------------------------------"; + } + + * { + line-height: 1.5; + } + + html { + background: rgb(245, 245, 225); + color: rgb(0, 0, 30); + } + + body { + max-width: 48em; + margin: 0 auto; + padding: 1em; + font-family: "Calibri", sans-serif; + font-size: 1.05rem; + } + + p { + line-height: 1.7; + } + + :link { + color: #00e; + } + + :visited { + color: #528; + } + + :link:focus, + :visited:focus, + :link:hover, + :visited:hover { + color: #e30; + } + + :link:active, + :visited:active { + color: #e00; + } + + center, + [align] { + text-align: left; + } + + b:not(.jancss-probably-structure), + u, + blink { + font-weight: inherit; + font-style: inherit; + text-decoration: inherit + } + + b.jancss-probably-structure { + font-size: larger; + } + + .jancss-probably-layout { + font: inherit; + } + + -jancss-comment { content: + "Headers --------------------------------------------------"; + } + + h1:not(.jancss-probably-layout), + h2:not(.jancss-probably-layout), + h3:not(.jancss-probably-layout) { + font-family: "Cambria", serif; + } + + h1, h1.jancss-probably-layout { + border-bottom: 1px solid #888; + font-size: 200%; + font-weight: 100; + } + + h2, h2.jancss-probably-layout * { + border-bottom: 1px solid #bbb; + font-size: 150%; + font-weight: 100; + } + + h3, h3.jancss-probably-layout { + border-bottom: 1px dotted #bbb; + font-size: 117%; + font-weight: 100; + } + + h1.jancss-probably-layout *, + h2.jancss-probably-layout *, + h3.jancss-probably-layout * { + font-size: 1rem; + } + + -jancss-comment { content: + "Links in headers (probably permalinks) -------------------"; + } + + h1 a[href]:not(:hover), + h2 a[href]:not(:hover), + h3 a[href]:not(:hover) { + text-decoration: none; + } + + h1 a[href]::after, + h2 a[href]::after, + h3 a[href]::after { + font-size: 75%; + content: " #"; + } + + -jancss-comment { content: + "Pre-formatted text and source code -----------------------"; + } + + pre { + padding: 1ex; + border: 1px dotted; + } + + code, + pre, + .syntaxhighlighter, + .dp-highlighter { + font-family: "Consolas", monospace; + font-size: small; + background: #ffe; + } + + .dp-highlighter + pre[name="code"] { + display: none; + } + + -jancss-comment { content: + "Forms ----------------------------------------------------"; + } + + textarea { + width: 100%; + height: 32ex; + } + + -jancss-comment { content: + "Tables ---------------------------------------------------"; + } + + table.jancss-probably-for-data th, + table.jancss-probably-for-data td { + vertical-align: top; + text-align: left; + padding: 0.5ex; + } + + table.jancss-probably-for-data caption { + font-weight: bold; + border-bottom: 1px dotted; + } + + table.jancss-probably-for-layout td { + display: inline-block; + } + + table.jancss-probably-for-data tr:nth-child(odd) td:not(.jancss-active-col) { + background: #ffe; + } + + table.jancss-probably-for-data tr:hover td:not(.code), + table.jancss-probably-for-data .jancss-active-col { + background: #ffc; + } + + table.jancss-probably-for-data th, + table.jancss-probably-for-data tr td:not(.code):hover { + background: #ff9; + } + + table.jancss-probably-for-data th code, + table.jancss-probably-for-data td code { + background: inherit; + } + + -jancss-comment { content: + "Make images use the full page width ----------------------"; + } + + img, + input[type="image"], + object, + embed, + video, + audio, + iframe, + canvas, + :not(svg|*) > svg|* { + max-width: 100%; + } + + figure { + margin: 0; + } + + iframe { + width: 100%; + } + + iframe[class*="twitter"] { + min-height: 15em; + } + + -jancss-comment { content: + "Dim images and media until :hover ------------------------"; + } + + body:not(:hover) img, + body:not(:hover) input[type="image"], + body:not(:hover) object, + body:not(:hover) embed, + body:not(:hover) video, + body:not(:hover) audio, + body:not(:hover) iframe, + body:not(:hover) canvas, + body:not(:hover) :not(svg|*) > svg|* { + opacity: 0.25; + } + + -jancss-comment { content: + "Limit icon dimensions --------------------------------"; + } + + a[href*="facebook.com"] svg, + a[href*="instagram.com"] svg, + a[href*="twitter.com"] svg, + a[href*=".pinterest."] svg, + svg[id*="icon"], + svg[class*="icon"], + svg[class*="inline"], + svg[data-icon], + svg[role="img"], + [class*="icon"] svg, + [class*="Icon"] svg, + img[class*="icon"][src*=".svg"], + img[class*="Icon"][src*=".svg"], + span > svg, + button svg, + [class*="button"] svg, + [role*="button"] svg, + [class*="controls"] svg, + .svg-icon, + .inline-icon, + .wp-smiley, + .smiley, + .emoticon, + :not(html).emoji { + max-width: 1.4em; + max-height: 1.4em; + } + + -jancss-comment { content: + "Make everything scrollable -------------------------------"; + } + + [style*="position: fixed"], + [style*="position:fixed"] { + position: static !important; + } + + -jancss-comment { content: + "Make side notes and pull quotes less conspicuous ---------"; + } + + aside:not(:hover), + [data-expander-id], + [id^="footnote_plugin_tooltip_text_"]:not(:hover), + blockquote[class*="quote"]:not(:hover), + q[class*="pull"]:not(:hover), + blockquote[class*="pull"]:not(:hover), + .quote-box:not(:hover), + .su-pullquote:not(:hover), + .pullquote:not(:hover), + .pullQuote:not(:hover), + .pull-quote:not(:hover) { + opacity: 0.25; + } + + -jancss-comment { content: + "Decrease common forum and metadata font size -------------"; + } + + .postprofile, + .signature { + font-size: smaller; + border-top: 1px dotted; + opacity: 0.5; + } + + -jancss-comment { content: + "Hide common social media elements ------------------------"; + } + + iframe[src*=".facebook.com/"], + iframe[src*=".twitter.com/widgets/"], + iframe[src*="//plusone.google.com/_/+1/"], + iframe[src*="//www.reddit.com/static/button/"], + iframe[src*="//s7.addthis.com/"], + iframe[src*="//www.stumbleupon.com/badge/embed/"], + iframe[src*="//widgets.bufferapp.com/"] { + width: 12em; + height: 4ex; + border: 1px dotted; + } + + .twtr-widget.twtr-scroll { + max-height: 30ex; + overflow: auto; + } + + .article__share { + display: none; + } + + #social_btns { + display: none; + } + + .taboola { + display: none; + } + + .social-media > .share { + display: none; + } + + :-moz-any( + div, + ul, + li + ):-moz-any( + :-moz-any( + [id*="social"], + [id*="Social"] + ):-moz-any( + [id*="media"], + [id*="Media"] + ):-moz-any( + [id*="share"], + [id*="Share"], + [id*="sharing"], + [id*="Sharing"] + ), + :-moz-any( + [id*="social"], + [id*="Social"] + [id*="share"], + [id*="Share"], + [id*="sharing"], + [id*="Sharing"] + ):-moz-any( + [id*="toolbar"], + [id*="Toolbar"], + [id*="buttons"], + [id*="Buttons"], + ), + :-moz-any( + [class*="social"], + [class*="Social"] + ):-moz-any( + [class*="media"], + [class*="Media"] + ):-moz-any( + [class*="share"], + [class*="Share"], + [class*="sharing"], + [class*="Sharing"] + ), + :-moz-any( + [class*="social"], + [class*="Social"] + [class*="share"], + [class*="Share"], + [class*="sharing"], + [class*="Sharing"] + ):-moz-any( + [class*="toolbar"], + [class*="Toolbar"], + [class*="buttons"], + [class*="Buttons"], + ) + ) { + display: none; + } + + :matches( + div, + ul, + li + ):matches( + :matches( + [id*="social"], + [id*="Social"] + ):matches( + [id*="media"], + [id*="Media"] + ):matches( + [id*="share"], + [id*="Share"], + [id*="sharing"], + [id*="Sharing"] + ), + :matches( + [id*="social"], + [id*="Social"] + [id*="share"], + [id*="Share"], + [id*="sharing"], + [id*="Sharing"] + ):matches( + [id*="toolbar"], + [id*="Toolbar"], + [id*="buttons"], + [id*="Buttons"], + ), + :matches( + [class*="social"], + [class*="Social"] + ):matches( + [class*="media"], + [class*="Media"] + ):matches( + [class*="share"], + [class*="Share"], + [class*="sharing"], + [class*="Sharing"] + ), + :matches( + [class*="social"], + [class*="Social"] + [class*="share"], + [class*="Share"], + [class*="sharing"], + [class*="Sharing"] + ):matches( + [class*="toolbar"], + [class*="Toolbar"], + [class*="buttons"], + [class*="Buttons"], + ) + ) { + display: none; + } + + -jancss-comment { content: + "Hide ad elements that slipped through my ad blocker ------"; + } + + iframe[id^="google_ads_"] { + display: none; + } + + -jancss-comment { content: + "Hide empty list items ------------------------------------"; + } + + li:empty, li.jancss-emptyish { + display: none; + } + + -jancss-comment { content: + "Make common navigation elements more compact -------------"; + } + + :-moz-any( + nav, + body [class*="avigat"], + body [id*="avigat"], + body [class*="-nav-"], + body [class*="nav-"], + body [class$="-nav"], + body [id*="-nav-"], + body [id*="nav-"], + body [id$="-nav"], + body [role="navigation"] + ) ul { + display: inline; + margin: 0; + padding: 0; + } + + :-webkit-any( + nav, + body [class*="avigat"], + body [id*="avigat"], + body [class*="-nav-"], + body [class*="nav-"], + body [class$="-nav"], + body [id*="-nav-"], + body [id*="nav-"], + body [id$="-nav"], + body [role="navigation"] + ) ul { + display: inline; + margin: 0; + padding: 0; + } + + :any( + nav, + body [class*="avigat"], + body [id*="avigat"], + body [class*="-nav-"], + body [class*="nav-"], + body [class$="-nav"], + body [id*="-nav-"], + body [id*="nav-"], + body [id$="-nav"], + body [role="navigation"] + ) ul { + display: inline; + margin: 0; + padding: 0; + } + + :-moz-any( + nav, + body [class*="avigat"], + body [id*="avigat"], + body [class*="-nav-"], + body [class*="nav-"], + body [class$="-nav"], + body [id*="-nav-"], + body [id*="nav-"], + body [id$="-nav"], + body [role="navigation"] + ) li { + display: inline; + margin: 0; + padding: 0 .5em; + border-right: 1px dotted; + } + + :-webkit-any( + nav, + body [class*="avigat"], + body [id*="avigat"], + body [class*="-nav-"], + body [class*="nav-"], + body [class$="-nav"], + body [id*="-nav-"], + body [id*="nav-"], + body [id$="-nav"], + body [role="navigation"] + ) li { + display: inline; + margin: 0; + padding: 0 .5em; + border-right: 1px dotted; + } + + :any( + nav, + body [class*="avigat"], + body [id*="avigat"], + body [class*="-nav-"], + body [class*="nav-"], + body [class$="-nav"], + body [id*="-nav-"], + body [id*="nav-"], + body [id$="-nav"], + body [role="navigation"] + ) li { + display: inline; + margin: 0; + padding: 0 .5em; + border-right: 1px dotted; + } + + -jancss-comment { content: + "Hide old cufón text replacement --------------------------"; + } + + .cufon-canvas canvas { + display: none; + } + + -jancss-comment { content: + "Make notes on decorrespondent.nl less conspicuous --------"; + } + + .contentitem-sidenote:not(:hover) > :not(.contentitem-sidenote-snippet), + .contentitem-infocard-toggle-container + .contentitem-infocard-contents:not(:hover) { + opacity: 0.25; + } + + .contentitem-sidenote:hover > :not(.contentitem-sidenote-snippet), + .contentitem-infocard-toggle-container + .contentitem-infocard-contents:hover { + background: #ffc; + } + + -jancss-comment { content: + "Hide the source text on Google Translate-d pages ---------"; + } + + .google-src-text { + display: none; + } + + -jancss-comment { content: + "Hide big ScrollMagic spacers, e.g. on Co.Design ----------"; + } + + .scrollmagic-pin-spacer { + display: none; + } + + -jancss-comment { content: + "Always hide our IFRAME used to restore console.log -------"; + } + + #xxxJanConsole { + display: none; + } + + */; }).toString() + .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '') + .replace(/\*\/\s*\;?\s*\}\s*$/, ''); + + /* The attributes to disable. */ + var attrs = [ + 'style', + 'background', 'bgcolor', 'color', 'text', 'link', 'vlink', 'alink', 'hlink', + 'table@width', 'colgroup@width', 'col@width', 'tr@width', 'td@width', 'th@width', 'table@height', 'tr@height', 'td@height', 'th@height', + 'img@width', 'img@height', + 'border', + 'frameborder', + 'align', + 'face', 'font@size', 'basefont@size' + ]; + + /* Elements to remove completely. */ + var elementsToRemoveSelectors = [ + '.bt-popin' /* Used on standaard.be. */ + ]; + + /* The selectors to try for the header elements, whose text content will be compared to the page title. The last match wins. */ + var headerSelectors = [ + '[class*="head"]:not(:empty)', + '[class*="Head"]:not(:empty)', + '[id*="head"]:not(:empty)', + '[id*="Head"]:not(:empty)', + '[role="heading"]', + '[class*="title"]:not(:empty)', + '[class*="Title"]:not(:empty)', + 'h1:not(:empty), h2:not(:empty), h3:not(:empty)', + 'h1:not(:empty)[itemprop~="name"], h2:not(:empty)[itemprop~="name"], h3:not(:empty)[itemprop~="name"]', + 'h1:not(:empty)[itemprop~="headline"], h2:not(:empty)[itemprop~="headline"], h3:not(:empty)[itemprop~="headline"]' + ]; + + var ancestorsForHeadersToIgnoreSelectors = [ + 'aside', + '.related-posts', + '.article-slider', + '.article-drawer' + ]; + + /* The selectors to try (in this order) for the first content element to scroll to when no suitable header was found. */ + var contentSelectors = [ + /* The most semantically rich elements should be used correctly so we + * can ass-u-me them to be the main content element, right? + */ + 'main h1:not(:empty)', + 'main header', + 'main h2:not(:empty)', + 'main', + 'body [itemprop="blogPost"] h1:not(:empty)', + 'body [itemprop="blogPost"] header', + 'body [itemprop="blogPost"] h2:not(:empty)', + 'body [itemprop="blogPost"]', + 'body [role="main"] h1:not(:empty)', + 'body [role="main"] header', + 'body [role="main"] h2:not(:empty)', + 'body [role="main"]', + 'body [role="document"] h1:not(:empty)', + 'body [role="document"] header', + 'body [role="document"] h2:not(:empty)', + 'body [role="document"]', + 'body [role="article"] h1:not(:empty)', + 'body [role="article"] header', + 'body [role="article"] h2:not(:empty)', + 'body [role="article"]', + 'body #main h1:not(:empty)', + 'body #main header', + 'body #main h2:not(:empty)', + 'body #main', + + /*
is also "semantically rich", but there are several sites + * that have a list of related articles, each in its own
. A + * "real" article would not have any
siblings. + */ + ':not(li) > article:only-of-type', + + /* Common IDs and classes for the main content element (e.g. weblog + * post IDs, newspaper articles, …) + */ + 'body #article', + 'body :not(#spotlight) > .article', + 'body .articleContent', + 'body #article_top', + 'body #article_body', + 'body #article_main', + 'body .post-body:not(.field-item)', + ':not(input):not(textarea).post', + ':not(input):not(textarea).blogpost', + ':not(input):not(textarea).blogPost', + 'body [id^="post0"]', + 'body [id^="post1"]', + 'body [id^="post2"]', + 'body [id^="post3"]', + 'body [id^="post4"]', + 'body [id^="post5"]', + 'body [id^="post6"]', + 'body [id^="post7"]', + 'body [id^="post8"]', + 'body [id^="post9"]', + 'body [id^="post-0"]', + 'body [id^="post-1"]', + 'body [id^="post-2"]', + 'body [id^="post-3"]', + 'body [id^="post-4"]', + 'body [id^="post-5"]', + 'body [id^="post-6"]', + 'body [id^="post-7"]', + 'body [id^="post-8"]', + 'body [id^="post-9"]', + 'body #entry', + 'body .entry', + 'body #content', + 'body .content', + 'body [id^="content"]', + 'body [class^="content"]', + 'body #main', + 'body .main', + + /* Consider the first header (in DOM order) to be the most important + * one and ass-u-me it is the start of the main content. + */ + 'h1:not(:empty)', + 'body #header', + 'header', + 'body .header', + 'h2:not(:empty)', + + /* When all else fails, just look for bigger text, which would + * probably be used instead of the appropriate header elements. + */ + 'big' + ]; + + /* Structure elements incorrectly used for layout purposes ("make it big and bold"). */ + var structureElementsForLayoutSelectors = [ + '//*[contains(" h1 h2 h3 h4 h5 h6 h7 ", concat(" ", local-name(), " ")) and string-length(normalize-space()) > 120]' + ]; + + /* Layout elements incorrectly used for structure purposes ("bold means header"). */ + var layoutElementsForStructureSelectors = [ + /* Because there is no support for the Selectors Level 4 "subject of + * a selector" syntax yet (or any definite syntax, for that matter), + * I simply ass-u-me in the code below that the subject is a "B" + * element. Either the result of the selector, or the previous + * element sibling. + */ + 'b:first-child + :empty', + ':empty + b + :empty', + ':empty + b:last-child', + 'div > b:only-child, p > b:only-child' + ]; + + /* URI pattern for syntax highlighting style sheets. */ + var syntaxHighlightHrefRegex = /\b((syntax|pygments)(hi(ghlight(er)?|lite(r)?))?|sh(Core|Theme[^.]*)|geshi|codecolorer)[./]/i; + + /* Keep track of which elements have had their event handlers + * disabled/re-enabled. + */ + var elementsWithToggledEventHandlers = {}; + + var eventHandlerAttributesToToggle = [ + 'oncontextmenu', + 'onshow', + + 'oninput', + 'onkeydown', + 'onkeyup', + 'onkeypress', + + 'onmousedown', + 'onmouseup', + 'onmouseenter', + 'onmouseleave', + 'onmouseover', + 'onmouseout', + 'onmousemove', + + 'onresize', + + 'onscroll', + 'onwheel', + + 'onselect', + 'onselectstart', + 'onselectionchange' + ]; + + /* All main content elements (the one in the main document and those + * nested in any IFRAMEs etc.) */ + var contentElements = []; + + /* The main function. */ + (function execute(document) { + function addClass(element, classNames) { + /* HTMLElement.classList does not work on iOS 4's Safari, so this is a fallback. */ + classNames.split(/\s+/).forEach(function (className) { + element.className = ((' ' + element.className + ' ').replace(' ' + className.trim() + ' ', '') + ' ' + className).trim(); + }); + } + + function removeClass(element, classNames) { + classNames.split(/\s+/).forEach(function (className) { + element.className = (' ' + element.className + ' ').replace(' ' + className.trim() + ' ', '').trim(); + }); + } + + function toArray(arrayLike) { + return Array.prototype.slice.call(arrayLike); + } + + var all = toArray(document.getElementsByTagName('*')), + ourStyleSheet = document.getElementById('jancss'), + allStyleSheets = toArray(document.styleSheets), + prettyPrintStyleSheet, + matches; + + /* Special hack for The Guardian (and possibly others), which re-enables the CSS because it detects a change in font size. */ + window.TextResizeDetector && TextResizeDetector.stopDetector && TextResizeDetector.stopDetector(); + + /* Clear all scheduled callbacks. Naively ass-u-me that any call to + * setTimeout/setInterval returns the next ID from a monotonically + * increasing function that is used for both timeout and interval + * IDs. Therefore, to clear all timeouts and intervals, it suffices + * to get a new timeout ID and then clear everything up to that ID. + * + * Though the HTML5 specification says nothing about the return value + * of setTimeout/setInterval, this appears to work in Firefox 22, + * Chrome 27, Opera 12 and Safari 5. + */ + var maxTimeoutId = setTimeout(function () { + for (var i = 1; i < maxTimeoutId; i++) { + clearTimeout(i); + clearInterval(i); + } + }, 4); /* 4 ms is the minimum timeout as per HTML5. */ + + /* Now clear all the requested animation frame callbacks. Again, this + * naively assumes the ID will increment one by one. MDN explicitly + * advises against assumptions such as this one: https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame#Return_value + */ + var requestAnimationFrame = window.requestAnimationFrame + || window.mozRequestAnimationFrame + || window.webkitRequestAnimationFrame + || window.msRequestAnimationFrame + || function () { }; + + var cancelAnimationFrame = window.cancelAnimationFrame + || window.mozCancelAnimationFrame + || window.webkitCancelAnimationFrame + || window.msCancelAnimationFrame + || function () { }; + + var maxAnimationFrameRequestId = requestAnimationFrame(function () { + for (i = 1; i < maxAnimationFrameRequestId * 2; i++) { + cancelAnimationFrame(i); + } + + /* Log requests to the original requestAnimationFrame. */ + window.requestAnimationFrame = function (callback) { + var callbackSource = callback.toSource && callback.toSource(); + if (callbackSource && callbackSource.indexOf('Readable++ requestAnimationFrame interceptor') === -1) { + console.log('Readable++: intercepted call to requestAnimationFrame at ' + new Date()); + console.log('Readable++: callback for requestAnimationFrame: ' + callbackSource); + } + }; + }); + + /* While in Readable++ mode, disable some elements' event handlers. + * This prevents hijacking events like "scroll" and "resize", which + * can be abused to annoy me with visual effects and whatnot, and + * "contextmenu" and "selectstart", which are clearly defined as + * universal and inalienable human rights. Look it up at your local + * Wikipedia office. + */ + [window, document, document.documentElement, document.body].forEach(function (elem) { + /* In non-HTML documents, elements like document.body can be + * null. */ + if (!elem) { + return; + } + + /* Because the window for IFRAMEs is the same as the outer + * document's window, we need to keep track of wether we + * have toggled the event handlers. Otherwise, they might + * get disabled and re-enabled immediately after. + */ + if (elementsWithToggledEventHandlers[elem]) { + return; + } + + elementsWithToggledEventHandlers[elem] = true; + + /* Toggle selected event handlers that have been set using + * "elem.oneventx = function () { … };" + */ + eventHandlerAttributesToToggle.forEach(function (attrib) { + if (elem['jancss-' + attrib]) { + elem[attrib] = elem['jancss-' + attrib]; + delete elem['jancss-' + attrib]; + } else if (elem[attrib]) { + elem['jancss-' + attrib] = elem[attrib]; + elem[attrib] = function () { }; + } + }); + + /* Toggle all event handlers that have been set using jQuery. */ + if (typeof jQuery === 'function') { + /* Since jQuery 1.7. */ + if (typeof jQuery.hasData === 'function' && jQuery.hasData(elem)) { + /* Spotted in the wild: "jQuery._data is undefined". */ + if (typeof jQuery._data !== 'function') { + return; + } + + var data = jQuery._data(elem); + if (data.jancssEvents) { + data.events = data.jancssEvents; + delete data.jancssEvents; + + jQuery._data(elem, data); + + return; + } else if (data.events) { + data.jancssEvents = data.events; + delete data.events; + + jQuery._data(elem, data); + + return; + } + } + + + /* Before jQuery 1.7 and after jQuery 1.2.3 */ + if (jQuery.fn.data) { + var $elem = jQuery(elem); + var eventsData = $elem.data('events'); + var jancssEventsData = $elem.data('jancssEvents'); + if (jancssEventsData) { + $elem.data('events', jancssEventsData); + $elem.removeData('jancssEvents'); + } else if (eventsData) { + $elem.data('jancssEvents', eventsData); + $elem.removeData('events'); + } + } + } + }); + + /* The code above does not work for event listeners added using + * addEventListener. Some sites listen for the "resize" event and + * then reposition elements by setting their style directly. To + * counteract this, simply delete all "style" attributes that get set + * while our style sheet is enabled. That'll show 'em! + */ + if (typeof MutationObserver === 'function' && !document.jancssHasMutationObserver) { + document.jancssHasMutationObserver = true; + var observer = new MutationObserver(function (mutations) { + if (ourStyleSheet.disabled) { + return; + } + + mutations.forEach(function(mutation) { + if (!mutation.target.hasAttribute('style') || mutation.target.id === 'xxxJanConsole' || mutation.target.xxxJanReadableAllowStyle) { + return; + } + + console.log('Readable++: removing "style" attribute set while in Readable++ mode on element ', mutation.target); + mutation.target.removeAttribute(mutation.attributeName); + }); + }); + + observer.observe(document, { + attributes: true, + attributeFilter: ['style'], + subtree: true + }); + } + + /* Load bLazy.js "retina" images. This is more specific than the + * generic lazy-loading attributes below, and needs special handling + * because it specifies multiple sources in one attribute. + */ + toArray(document.querySelectorAll('img.b-lazy[data-src*="|"]')).forEach(function (img) { + var attribute = 'data-src'; + var sources = img.getAttribute(attribute).split('|'); + img.src = sources.pop(); + img.removeAttribute(attribute); + }); + + /* Load Riloadr "