├── .env.development ├── .env.production ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── development.md ├── dist ├── theme │ ├── github.html │ ├── zhihu.html │ └── zhihu_new.html └── widget.js ├── images ├── chenghao-zhihu.png ├── chenghao-zhihu_new.png ├── chenghao.png ├── lks.jpg ├── logo.png ├── uid.png └── zhihu.ico ├── package.json ├── run_dev.js └── src ├── card.js ├── index.html ├── prod_test.html ├── theme ├── github.css ├── github.html ├── zhihu.css ├── zhihu.html ├── zhihu_new.css └── zhihu_new.html └── widget.js /.env.development: -------------------------------------------------------------------------------- 1 | ZHIHU_API_URL="https://zhihu-card.info:8443" 2 | THEME_URL=. 3 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | ZHIHU_API_URL="https://zhihu-card.info:8443" 2 | THEME_URL="https://laike9m.github.io/zhihu-card/dist" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | github-cards 2 | .DS_Store 3 | test.py 4 | jsdelivr/release_test.html 5 | node_modules/ 6 | 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | env/ 17 | bin/ 18 | build/ 19 | develop-eggs/ 20 | eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # Installer logs 31 | pip-log.txt 32 | pip-delete-this-directory.txt 33 | 34 | # Unit test / coverage reports 35 | htmlcov/ 36 | .tox/ 37 | .coverage 38 | .cache 39 | nosetests.xml 40 | coverage.xml 41 | 42 | # Translations 43 | *.mo 44 | 45 | # Mr Developer 46 | .mr.developer.cfg 47 | .project 48 | .pydevproject 49 | 50 | # Rope 51 | .ropeproject 52 | 53 | # Django stuff: 54 | *.log 55 | *.pot 56 | 57 | # Sphinx documentation 58 | docs/_build/ 59 | 60 | yarn.lock 61 | package-lock.json 62 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | liCOPYRIGHT (c) 2016 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 2022.4.24 更新: 由于知乎改了 OAuth 接口,且依赖库 zhihu-oauth 也不再更新,本项目已无法正常工作。感谢用户们这五年的信赖与支持。 2 | 3 | 4 | 5 | ![](images/logo.png) 6 | 7 | ## 用卡片展示你的知乎账户(Try it!) 8 | 9 | [(Eng ver.)](#english-version) 10 | 11 | 12 | 13 | 14 | ## 使用 15 | 16 | 使用个人网址的最后一部分作为 `data-userhash` 的值,如下: 17 | ![](images/uid.png) 18 | 19 | ```html 20 |
21 | 22 | ``` 23 | 24 | 注意 `widget.js` 一定要放在 `
` 的后面。 25 | 26 | 其它可用的 `data-xx` 参数包括: 27 | * `theme`: 卡片外观主题,包括 `zhihu`(default), `zhihu_new` 和 `github` 28 | * `width`: 卡片宽度,默认值是 400 29 | * `height`: 卡片高度 30 | * `button`: 是否显示“关注”按钮,取值为 `yes`(default)、`no` 31 | * `description`: 在 `github` 主题中是否显示用户个人简介,取值为 `yes`(default)、`no` 32 | * `suffix`: 显示在用户名之后的字符串,默认为空 33 | * `key1`, `key2`, `key3`: 卡片的三栏中显示数值的类型,取值和含义如下: 34 | 35 | | 取值 | 含义 | 36 | | -------- | ----- | 37 | | ask | 提问数量 | 38 | | answer | 回答数量 | 39 | | post | 文章数量 | 40 | | agree | 赞同数量 | 41 | | thanks | 感谢数量 | 42 | | follower | 关注者数量 | 43 | 44 | 默认值 `key1=answer, key2=agree, key3=follower` 45 | 46 | ## 例子 47 | ```html 48 |
50 | 51 | ``` 52 | 53 | # English Version 54 | 55 | Card to show your profile on [zhihu.com](https://www.zhihu.com/). 56 | 57 | ## Usage 58 | 59 | Use the last part of your homepage url as `data-userhash`'s value, like this: 60 | ![](images/uid.png) 61 | 62 | ```html 63 |
64 | 65 | ``` 66 | 67 | Make sure to place `widget.js` behind/under `
`. 68 | 69 | Available data parameters are: 70 | * `theme`: card appearance theme, options: `zhihu`(default), `zhihu_new` and `github` 71 | * `width`: card width, default is 400 72 | * `height`: card height 73 | * `button`: whether to show "follow" button,options: `yes`(default), `no` 74 | * `description`: when using `github` theme, whether to show user description, options: `yes`(default), `no` 75 | * `suffix`: string shown after user name, default is empty 76 | * `key1`, `key2`, `key3`: control values displayed in three columns, available values and their meaning are shown below: 77 | 78 | | value | meaning | 79 | | -------- | ------------------- | 80 | | ask | number of questions | 81 | | answer | number of answers | 82 | | post | number of posts | 83 | | agree | number of agree | 84 | | thanks | number of thanks | 85 | | follower | number of followers | 86 | 87 | default: `key1=answer, key2=agree, key3=follower` 88 | 89 | ## Example 90 | ```html 91 |
93 | 94 | ``` 95 | 96 | ## 致谢 97 | 特别感谢 @lepture 和他的 [github-cards](https://github.com/lepture/github-cards) 库。zhihu-card 的前端部分完全是照着 github-cards 写的。 98 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /development.md: -------------------------------------------------------------------------------- 1 | ### 安装依赖 2 | 3 | ```bash 4 | $ npm i 5 | ``` 6 | 7 | ### 启动开发服务器 8 | 9 | ```bash 10 | $ npm run dev 11 | ``` 12 | 13 | 开发服务器支持热更新,更改代码浏览器实时变化。 14 | 15 | ### 构建 16 | 17 | ```bash 18 | $ npm run build 19 | ``` 20 | 21 | ### 测试生产文件 22 | 23 | ```bash 24 | $ npm run prodtest 25 | ``` 26 | -------------------------------------------------------------------------------- /dist/theme/github.html: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /dist/theme/zhihu.html: -------------------------------------------------------------------------------- 1 | 32 | -------------------------------------------------------------------------------- /dist/theme/zhihu_new.html: -------------------------------------------------------------------------------- 1 | 60 | -------------------------------------------------------------------------------- /dist/widget.js: -------------------------------------------------------------------------------- 1 | parcelRequire=function(e,r,t,n){var i,o="function"==typeof parcelRequire&&parcelRequire,u="function"==typeof require&&require;function f(t,n){if(!r[t]){if(!e[t]){var i="function"==typeof parcelRequire&&parcelRequire;if(!n&&i)return i(t,!0);if(o)return o(t,!0);if(u&&"string"==typeof t)return u(t);var c=new Error("Cannot find module '"+t+"'");throw c.code="MODULE_NOT_FOUND",c}p.resolve=function(r){return e[t][1][r]||r},p.cache={};var l=r[t]=new f.Module(t);e[t][0].call(l.exports,p,l,l.exports,this)}return r[t].exports;function p(e){return f(p.resolve(e))}}f.isParcelRequire=!0,f.Module=function(e){this.id=e,this.bundle=f,this.exports={}},f.modules=e,f.cache=r,f.parent=o,f.register=function(r,t){e[r]=[function(e,r){r.exports=t},{}]};for(var c=0;c", 7 | "license": "MIT", 8 | "scripts": { 9 | "dev": "node run_dev.js", 10 | "build": "parcel build src/widget.js src/theme/*.html", 11 | "prodtest": "parcel src/prod_test.html --open" 12 | }, 13 | "devDependencies": { 14 | "cssnano": "^4.1.10", 15 | "express": "^4.17.1", 16 | "parcel-bundler": "^1.12.4", 17 | "parcel-plugin-inline-source": "^1.0.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /run_dev.js: -------------------------------------------------------------------------------- 1 | const Bundler = require('parcel-bundler'); 2 | const express = require('express'); 3 | 4 | const bundler = new Bundler(['src/index.html', 'src/theme/*.html']); 5 | const app = express(); 6 | 7 | app.get('/', (req, res, next) => { 8 | req.url = '/index.html'; 9 | app._router.handle(req, res, next); 10 | }); 11 | 12 | app.use(bundler.middleware()); 13 | 14 | const port = Number(process.env.PORT || 1234); 15 | require('parcel-bundler/lib/utils/openInBrowser')(`http://localhost:${port}`, true); 16 | app.listen(port); 17 | console.log(`listening at http://localhost:${port}`); 18 | -------------------------------------------------------------------------------- /src/card.js: -------------------------------------------------------------------------------- 1 | function querystring() { 2 | var href = window.location.href, 3 | kv; 4 | var params = href.slice(href.indexOf('?') + 1).split('&'); 5 | var qs = []; 6 | 7 | for (i = 0; i < params.length; i++) { 8 | kv = params[i].split('='); 9 | qs.push(kv[0]); 10 | qs[kv[0]] = kv[1]; 11 | } 12 | return qs; 13 | } 14 | 15 | var qs = querystring(); 16 | var urlRoot = process.env.ZHIHU_API_URL; 17 | 18 | (function(d) { 19 | var apiUrl = urlRoot + '/v1/user/', 20 | userUrl = "https://www.zhihu.com/people/", 21 | i; 22 | var eng2ch = { 23 | "ask": "提问", 24 | "answer": "回答", 25 | "post": "文章", 26 | "agree": "赞同", 27 | "thanks": "感谢", 28 | "follower": "关注者" 29 | }; 30 | var eng2path = { 31 | "ask": "asks", 32 | "answer": "answers", 33 | "post": "posts", 34 | "agree": "", 35 | "thanks": "", 36 | "follower": "followers" 37 | }; 38 | 39 | function store(key, value) { 40 | try { 41 | if (window.localStorage) { 42 | if (value) { 43 | value._timestamp = new Date().valueOf(); 44 | localStorage[key] = JSON.stringify(value); 45 | } else { 46 | var ret = localStorage[key]; 47 | if (ret) { 48 | return JSON.parse(ret); 49 | } 50 | return null; 51 | } 52 | } 53 | } catch (e) {} 54 | } 55 | 56 | function valueof() {} 57 | 58 | function template(data) { 59 | // 填充模版中的变量 60 | var t = d.getElementById('zhihu-card'); 61 | var regex = /{([^}]+)}/g; 62 | var text = t.innerHTML; 63 | var m = text.match(regex); 64 | for (i = 0; i < m.length; i++) { 65 | // text = text.replace(m[i], valueof(data, m[i].slice(1, -1))); 66 | text = text.replace(m[i], data[m[i].slice(1, -1)]); 67 | } 68 | return text; 69 | } 70 | 71 | function request(url, callback) { 72 | var cache = store(url); 73 | if (cache && cache._timestamp) { 74 | // cache for 6 hours 75 | if (new Date().valueOf() - cache._timestamp < 21600000) { 76 | return callback(cache); 77 | } 78 | } 79 | var xhr = new XMLHttpRequest(); 80 | xhr.open('GET', url, true); 81 | xhr.onload = function() { 82 | callback(JSON.parse(xhr.response)); 83 | }; 84 | xhr.send(); 85 | } 86 | 87 | // 填充 target, set iframe height 88 | function linky(card) { 89 | var links = card.getElementsByTagName('a'); 90 | for (i = 0; i < links.length; i++) { 91 | (function(link) { 92 | link.target = '_' + (qs.target || 'blank'); 93 | })(links[i]); 94 | } 95 | d.body.appendChild(card); 96 | if (qs.description == 'no') { 97 | var des = d.getElementsByClassName('footer')[0]; 98 | if (des) { 99 | des.setAttribute('style', 'display:none'); 100 | } 101 | } 102 | if (qs.button == 'no') { 103 | var btn = d.getElementsByClassName('button')[0]; 104 | btn.parentNode.removeChild(btn); 105 | } 106 | d.body.className = 'ready'; 107 | if (parent !== self && parent.postMessage) { 108 | var height = Math.max( 109 | d.body.scrollHeight, 110 | d.documentElement.scrollHeight, 111 | d.body.offsetHeight, 112 | d.documentElement.offsetHeight, 113 | d.body.clientHeight, 114 | d.documentElement.clientHeight 115 | ); 116 | parent.postMessage({ 117 | height: height, 118 | sender: qs.identity || '*' 119 | }, '*'); 120 | } 121 | } 122 | 123 | function zhihuCard(userhash) { 124 | var url = apiUrl + userhash; 125 | request(url, function(data) { 126 | data = data || {}; 127 | var defaults = '?'; // 默认显示的字符 128 | // message 存在说明data没有获取到数据,不存储,用 cache里的数据 129 | if (typeof(data.name) == 'undefined') { 130 | data = store(url) || data; 131 | } else { 132 | store(url, data); 133 | } 134 | var key1 = qs.key1, 135 | key2 = qs.key2, 136 | key3 = qs.key3; 137 | data['key1_data'] = numberic(data[key1]) || defaults; 138 | data['key2_data'] = numberic(data[key2]) || defaults; 139 | data['key3_data'] = numberic(data[key3]) || defaults; 140 | data['key1'] = eng2ch[key1]; 141 | data['key2'] = eng2ch[key2]; 142 | data['key3'] = eng2ch[key3]; 143 | data['key1_url'] = userUrl + data.domain + '/' + eng2path[key1]; 144 | data['key2_url'] = userUrl + data.domain + '/' + eng2path[key2]; 145 | data['key3_url'] = userUrl + data.domain + '/' + eng2path[key3]; 146 | data['suffix'] = decodeURI(qs.suffix); 147 | 148 | var card = d.createElement('div'); 149 | card.className = 'zhihu-card'; 150 | card.innerHTML = template(data); 151 | linky(card); 152 | }); 153 | } 154 | 155 | function numberic(num) { 156 | if (num == null || typeof(num) == "undefined") return null; 157 | if (num < 10000) { 158 | return num.toString(); 159 | } 160 | num = parseInt(num / 1000); 161 | return num.toFixed(0) + 'k'; 162 | } 163 | 164 | var noreferrer = d.createElement('meta'); 165 | noreferrer.name = "referrer"; 166 | noreferrer.content = "no-referrer"; 167 | d.head.appendChild(noreferrer); 168 | zhihuCard(qs.userhash); 169 | 170 | function escape(text) { 171 | return text.replace(//g, '>'); 172 | } 173 | })(document); -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
5 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/prod_test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/theme/github.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-size: 14px; 5 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 6 | overflow: hidden; 7 | } 8 | body.ready { 9 | border: 1px solid #eee; 10 | border-radius: 5px; 11 | border-color: #eee #ddd #bbb; 12 | box-shadow: rgba(0, 0, 0, 0.14) 0px 1px 3px; 13 | } 14 | 15 | .zhihu-card { 16 | border-radius: 5px; 17 | padding: 8px 8px 0; 18 | background: #fff; 19 | color: #555; 20 | position: relative; 21 | } 22 | 23 | .zhihu-card a { 24 | text-decoration: none; 25 | color: #4183c4; 26 | outline: 0; 27 | } 28 | .zhihu-card a:hover { 29 | text-decoration: underline; 30 | } 31 | 32 | .zhihu-card .header { 33 | position: relative; 34 | } 35 | .zhihu-card .button { 36 | position: absolute; 37 | top: 0; 38 | right: 0; 39 | padding: 4px 8px 4px 7px; 40 | color: #555; 41 | text-shadow: 0 1px 0 #fff; 42 | border: 1px solid #d4d4d4; 43 | border-radius: 3px; 44 | font-size: 13px; 45 | font-weight: bold; 46 | line-height: 14px; 47 | background-color: #e6e6e6; 48 | background-image: -webkit-linear-gradient(#fafafa, #eaeaea); 49 | background-image: -moz-linear-gradient(#fafafa, #eaeaea); 50 | background-image: -ms-linear-gradient(#fafafa, #eaeaea); 51 | background-image: linear-gradient(#fafafa, #eaeaea); 52 | } 53 | .zhihu-card .button:hover { 54 | color: #fff; 55 | text-decoration: none; 56 | background-color: #3072b3; 57 | background-image: -webkit-linear-gradient(#599bdc, #3072b3); 58 | background-image: -moz-linear-gradient(#599bdc, #3072b3); 59 | background-image: -ms-linear-gradient(#599bdc, #3072b3); 60 | background-image: linear-gradient(#599bdc, #3072b3); 61 | border-color: #518cc6 #518cc6 #2a65a0; 62 | text-shadow: 0 -1px 0 rgba(0,0,0,.25); 63 | } 64 | 65 | /* user card */ 66 | .zhihu-card .header { 67 | padding: 3px 0 4px 57px; 68 | min-height: 48px; 69 | } 70 | .zhihu-card .header a { 71 | color: #707070; 72 | text-decoration: none; 73 | } 74 | .zhihu-card .header a:hover strong { 75 | text-decoration: underline; 76 | } 77 | 78 | .zhihu-card img { 79 | position: absolute; 80 | top: 0; 81 | left: 0; 82 | width: 48px; 83 | height: 48px; 84 | background: #fff; 85 | border-radius: 4px; 86 | } 87 | .zhihu-card strong { 88 | display: block; 89 | color: #292f33; 90 | font-size: 16px; 91 | line-height: 1.6; 92 | } 93 | 94 | .zhihu-card ul { 95 | text-transform: uppercase; 96 | font-size: 12px; 97 | color: #707070; 98 | list-style-type: none; 99 | margin: 0; 100 | padding: 0; 101 | border-top: 1px solid #eee; 102 | border-bottom: 1px solid #eee; 103 | zoom: 1; 104 | } 105 | .zhihu-card ul:after { 106 | display: block; 107 | content: ''; 108 | clear: both; 109 | } 110 | .zhihu-card .status a { 111 | color: #707070; 112 | text-decoration: none; 113 | } 114 | .zhihu-card .status a:hover { 115 | color: #4183c4; 116 | } 117 | .zhihu-card .status li { 118 | float: left; 119 | padding: 4px 18px; 120 | border-left: 1px solid #eee; 121 | } 122 | .zhihu-card .status li:first-child { 123 | border-left: 0; 124 | padding-left: 0; 125 | } 126 | .zhihu-card .footer { 127 | font-size: 12px; 128 | font-weight: 700; 129 | padding: 11px 0 10px; 130 | color: #646464; 131 | } 132 | .zhihu-card .footer a { 133 | color: #646464; 134 | } 135 | -------------------------------------------------------------------------------- /src/theme/github.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/theme/zhihu.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 0; 3 | margin: 0; 4 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; 5 | font-size: 13px; 6 | line-height: 1.7; 7 | word-wrap: break-word; 8 | color: #222; 9 | background-color: #fff; 10 | overflow: hidden; 11 | } 12 | a { 13 | color: #259; 14 | text-decoration: none; 15 | } 16 | .zh-profile-card { 17 | background: #fff; 18 | border: solid 1px #ccc; 19 | border-radius: 5px; 20 | overflow: hidden; 21 | } 22 | body.zhi { 23 | padding-top: 46px; 24 | -webkit-font-smoothing: subpixel-antialiased; 25 | } 26 | .zh-profile-card .upper { 27 | background: #fff; 28 | padding-left: 66px; 29 | min-height: 50px; 30 | } 31 | .zh-profile-card .upper, .zh-profile-card .lower { 32 | border: 14px solid transparent; 33 | } 34 | .zh-profile-card .lower { 35 | background: #fafafa; 36 | } 37 | .zh-profile-card .upper a.avatar-link { 38 | position: relative; 39 | } 40 | a:link { 41 | -webkit-tap-highlight-color: rgba(225, 225, 225, .5); 42 | } 43 | .zh-profile-card .upper img.Avatar { 44 | position: absolute; 45 | left: -66px; 46 | } 47 | .Avatar--xs { 48 | width: 50px; 49 | height: 50px; 50 | } 51 | .Avatar { 52 | border-radius: 3px; 53 | background-color: #eee; 54 | } 55 | img { 56 | border: 0; 57 | } 58 | .zh-profile-card .upper span.name { 59 | font-size: 16px; 60 | font-weight: 700; 61 | } 62 | .zh-profile-card .upper div.tagline { 63 | font-size: 14px; 64 | color: #222; 65 | padding-top: 4px; 66 | } 67 | .clearfix:before, .clearfix:after { 68 | display: table; 69 | content: ""; 70 | } 71 | .clearfix:after { 72 | clear: both; 73 | } 74 | .zh-profile-card .lower .meta .item:first-child { 75 | padding-left: 0; 76 | } 77 | .zh-profile-card .lower .meta .item { 78 | float: left; 79 | padding: 0 16px; 80 | border-right: 1px solid #eee; 81 | color: inherit; 82 | text-decoration: none; 83 | } 84 | .zh-profile-card .lower .meta .item .value, .zh-profile-card .lower .meta .item .key { 85 | display: block; 86 | text-align: center; 87 | } 88 | .zh-profile-card .lower .meta .item .value { 89 | font-size: 15px; 90 | font-weight: 700; 91 | } 92 | .zh-profile-card .lower .meta .item .key { 93 | font-size: 14px; 94 | color: #999; 95 | } 96 | .zh-profile-card .lower .meta .item { 97 | color: inherit; 98 | } 99 | .zh-profile-card .lower .meta .item:last-child { 100 | border-right: 0 none; 101 | } 102 | .zh-profile-card .lower .operation .zg-btn { 103 | font-size: 13px; 104 | } 105 | .zh-profile-card .lower .operation .zg-btn, .zh-profile-card .lower .operation .zg-btn-white, .zh-profile-card .lower .operation button { 106 | float: right; 107 | line-height: 32px; 108 | margin-top: 8px; 109 | vertical-align: middle; 110 | } 111 | .zg-btn-green, .zg-btn-follow { 112 | width: auto; 113 | min-width: 78px; 114 | color: #3e5e00!important; 115 | text-shadow: 0 1px 0 rgba(255, 255, 255, .3); 116 | background: linear-gradient(to bottom, #adda4d, #86b846); 117 | border: 1px solid #6d8f29; 118 | box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset, 0 1px 0 rgba(0, 0, 0, .2); 119 | } 120 | .zg-btn { 121 | display: block; 122 | text-align: center; 123 | min-width: 78px; 124 | font-size: 12px; 125 | text-decoration: none!important; 126 | padding: 1px; 127 | font-weight: 400; 128 | line-height: 18px; 129 | border-radius: 3px; 130 | cursor: pointer; 131 | box-sizing: border-box; 132 | } 133 | button, input, select, textarea { 134 | margin: 0; 135 | font-family: inherit; 136 | } -------------------------------------------------------------------------------- /src/theme/zhihu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/theme/zhihu_new.css: -------------------------------------------------------------------------------- 1 | a { 2 | color: inherit; 3 | text-decoration: none; 4 | } 5 | 6 | .HoverCard { 7 | -webkit-box-shadow: 0 5px 20px rgba(26,26,26,.1); 8 | box-shadow: 0 5px 20px rgba(26,26,26,.1); 9 | background: #fff; 10 | border-radius: 2px; 11 | padding: 0 12px 16px; 12 | font-size: 14px; 13 | opacity: 1; 14 | -webkit-transition: opacity .3s ease; 15 | transition: opacity .3s ease; 16 | } 17 | 18 | .HoverCard-titleContainer { 19 | position: relative; 20 | display: -webkit-box; 21 | display: -ms-flexbox; 22 | display: flex; 23 | padding: 8px 0; 24 | border-bottom: 1px solid #f6f6f6; 25 | -webkit-box-align: center; 26 | -ms-flex-align: center; 27 | align-items: center; 28 | margin-top: 20px; 29 | } 30 | 31 | .HoverCard-titleText { 32 | display: -webkit-box; 33 | display: -ms-flexbox; 34 | display: flex; 35 | min-height: 42px; 36 | padding-bottom: 2px; 37 | margin-left: 84px; 38 | -webkit-box-orient: vertical; 39 | -webkit-box-direction: normal; 40 | -ms-flex-direction: column; 41 | flex-direction: column; 42 | -webkit-box-pack: center; 43 | -ms-flex-pack: center; 44 | justify-content: center; 45 | overflow: hidden; 46 | -webkit-box-flex: 1; 47 | -ms-flex: 1 1; 48 | flex: 1 1; 49 | } 50 | 51 | .HoverCard-title { 52 | font-size: 16px; 53 | font-weight: 500; 54 | } 55 | .HoverCard-subtitle { 56 | margin-top: 4px; 57 | font-weight: 400; 58 | } 59 | .HoverCard-subtitle, .HoverCard-title { 60 | overflow: hidden; 61 | text-overflow: ellipsis; 62 | white-space: nowrap; 63 | } 64 | 65 | .Avatar { 66 | position: absolute; 67 | top: -20px; 68 | border: 2px solid #fff; 69 | border-radius: 4px; 70 | background: #fff; 71 | } 72 | 73 | .ready { 74 | margin: 10px; 75 | } 76 | 77 | .HoverCard-item { 78 | padding: 8px 16px; 79 | text-align: center; 80 | border: 0; 81 | line-height: 1.75; 82 | } 83 | 84 | .NumberBoard { 85 | display: -webkit-box; 86 | display: -ms-flexbox; 87 | display: flex; 88 | } 89 | 90 | .NumberBoard-item.Button { 91 | border: 0; 92 | line-height: unset; 93 | font-size: unset; 94 | } 95 | 96 | .NumberBoard-item.Button:hover, 97 | .NumberBoard-item.Button:hover .NumberBoard-itemName, 98 | .NumberBoard-item.Button:hover .NumberBoard-itemValue { 99 | background: none; 100 | color: #175199; 101 | } 102 | 103 | .NumberBoard-item { 104 | -webkit-box-flex: 1; 105 | -ms-flex: 1 1; 106 | flex: 1 1; 107 | height: auto; 108 | padding: 0; 109 | line-height: inherit; 110 | background-color: transparent; 111 | border: none; 112 | border-radius: 0; 113 | } 114 | 115 | .Button { 116 | display: inline-block; 117 | padding: 0 16px; 118 | font-size: 14px; 119 | line-height: 32px; 120 | color: #8590a6; 121 | text-align: center; 122 | cursor: pointer; 123 | background: none; 124 | border: 1px solid; 125 | border-radius: 3px; 126 | } 127 | 128 | .NumberBoard-itemInner { 129 | text-align: center; 130 | line-height: 1.6; 131 | } 132 | 133 | .NumberBoard-itemName { 134 | font-size: 14px; 135 | color: #8590a6; 136 | } 137 | 138 | .NumberBoard-itemValue { 139 | display: inline-block; 140 | font-size: 18px; 141 | color: #1a1a1a; 142 | font-weight: 600; 143 | font-synthesis: style; 144 | } 145 | 146 | .HoverCard-buttons { 147 | margin-top: 16px; 148 | } 149 | 150 | .HoverCard-buttons .Button { 151 | width: 144px; 152 | box-sizing: border-box; 153 | } 154 | .primary { 155 | color: #fff; 156 | background-color: #0084ff; 157 | border-color: #0084ff; 158 | } 159 | .primary:hover { 160 | border-color: #0077e6; 161 | background-color: #0077e6; 162 | } 163 | .HoverCard-buttons a.Button { 164 | display: inline-flex; 165 | align-items: center; 166 | justify-content: center; 167 | } 168 | .Zi { 169 | margin-right: 4px; 170 | } 171 | 172 | .grey:hover { 173 | background-color: rgba(133,144,166,.06); 174 | } 175 | -------------------------------------------------------------------------------- /src/theme/zhihu_new.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/widget.js: -------------------------------------------------------------------------------- 1 | (function(d) { 2 | var base = process.env.THEME_URL; 3 | var i, 4 | count = 0; 5 | var client_url, client_id, client_secret, client_theme; 6 | 7 | function queryclass(name) { 8 | if (d.querySelectorAll) { 9 | return d.querySelectorAll("." + name); 10 | } 11 | var elements = d.getElementsByTagName("div"); 12 | var ret = []; 13 | for (i = 0; i < elements.length; i++) { 14 | if (~elements[i].className.split(" ").indexOf(name)) { 15 | ret.push(elements[i]); 16 | } 17 | } 18 | return ret; 19 | } 20 | 21 | function querydata(element, name) { 22 | return element.getAttribute("data-" + name); 23 | } 24 | 25 | function heighty(iframe) { 26 | if (window.addEventListener) { 27 | window.addEventListener( 28 | "message", 29 | function(e) { 30 | if (iframe.id === e.data.sender) { 31 | iframe.height = e.data.height; 32 | } 33 | }, 34 | false 35 | ); 36 | } 37 | } 38 | 39 | function render(card) { 40 | var theme = querydata(card, "theme") || "zhihu"; 41 | cardurl = base + "/theme/" + theme + ".html"; 42 | var userhash = querydata(card, "userhash"); 43 | if (!userhash) { 44 | return; 45 | } 46 | count += 1; 47 | var width = querydata(card, "width"); 48 | var height = querydata(card, "height"); 49 | var key1 = querydata(card, "key1") || "answer"; 50 | var key2 = querydata(card, "key2") || "agree"; 51 | var key3 = querydata(card, "key3") || "follower"; 52 | var button = querydata(card, "button") || "yes"; 53 | var description = querydata(card, "description") || "yes"; 54 | var suffix = querydata(card, "suffix") || ""; 55 | var identity = "zhcard-" + userhash + "-" + count; 56 | 57 | var iframe = d.createElement("iframe"); 58 | iframe.setAttribute("id", identity); 59 | iframe.setAttribute("frameborder", 0); 60 | iframe.setAttribute("scrolling", 0); 61 | iframe.setAttribute("allowtransparency", true); 62 | 63 | iframe.src = cardurl.concat( 64 | "?userhash=", 65 | userhash, 66 | "&identity=", 67 | identity, 68 | "&button=", 69 | button, 70 | "&description=", 71 | description, 72 | "&key1=", 73 | key1, 74 | "&key2=", 75 | key2, 76 | "&key3=", 77 | key3, 78 | "&suffix=", 79 | suffix 80 | ); 81 | iframe.width = width || Math.min(card.parentNode.clientWidth || 400, 400); 82 | if (height) { 83 | iframe.height = height; 84 | } 85 | heighty(iframe); 86 | card.parentNode.replaceChild(iframe, card); 87 | return iframe; 88 | } 89 | 90 | var cards = queryclass("zhihu-card"); 91 | for (i = 0; i < cards.length; i++) { 92 | render(cards[i]); 93 | } 94 | })(document); 95 | --------------------------------------------------------------------------------