├── .eslintrc.js ├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── blog ├── .eslintrc.js ├── favicon.ico ├── index.html ├── p │ ├── 2014 │ │ ├── 10 │ │ │ ├── QQ图片20141022210533.jpg │ │ │ ├── QQ图片20141022210537.jpg │ │ │ ├── QQ图片20141022214120.jpg │ │ │ └── free-your-html-body-tags.md │ │ ├── 12 │ │ │ └── test-on-javascript.md │ │ └── 09 │ │ │ ├── bug │ │ │ ├── close.png │ │ │ ├── gulp-plugins.png │ │ │ ├── notification.png │ │ │ ├── reference.png │ │ │ └── thanks.png │ │ │ └── gulp-eol-bug.md │ ├── 2015 │ │ ├── 01 │ │ │ ├── fs-auth.md │ │ │ ├── fs-auth │ │ │ │ ├── auth.png │ │ │ │ ├── decrypt.png │ │ │ │ ├── encrypt.png │ │ │ │ ├── overview.png │ │ │ │ └── shift.png │ │ │ └── why-no-semicolon.md │ │ └── 05 │ │ │ └── silent-one-year-old │ │ │ ├── chang.jpg │ │ │ ├── derek.jpg │ │ │ ├── index.md │ │ │ ├── jacson.jpg │ │ │ ├── jayden.png │ │ │ ├── jayin.jpg │ │ │ ├── silent.png │ │ │ └── todd.gif │ ├── 2016 │ │ └── 08 │ │ │ ├── silent-talk.md │ │ │ ├── 屏幕快照 2016-08-02 下午5.46.40.png │ │ │ └── 屏幕快照 2016-08-02 下午6.35.12.png │ ├── 2022 │ │ └── 09 │ │ │ ├── WX20220927-134112.png │ │ │ ├── WX20220927-134431.png │ │ │ ├── WX20220927-155434.png │ │ │ ├── WX20220927-160316.png │ │ │ ├── WX20220927-164233.png │ │ │ ├── WX20220927-164651.png │ │ │ ├── WX20220927-222427.png │ │ │ ├── WX20220928-175618.png │ │ │ ├── WX20220928-180550.png │ │ │ ├── blog-setup-via-github-fork.md │ │ │ ├── wtf-is-that-mac-icloud-handoff-en.md │ │ │ └── wtf-is-that-mac-icloud-handoff.md │ ├── aboutme.md │ ├── avatar.jpg │ ├── posts.md │ ├── projects │ │ ├── github-badge.svg │ │ ├── gitter-badge.svg │ │ ├── index.md │ │ ├── react-drag-sizing │ │ │ ├── README.md │ │ │ └── demo.gif │ │ ├── silent │ │ │ ├── README.md │ │ │ └── pic │ │ │ │ ├── Screenshot_from_2014-05-08_01-43-18.png │ │ │ │ ├── Screenshot_from_2014-05-08_01-48-37.png │ │ │ │ ├── Screenshot_from_2014-05-08_01-50-42.png │ │ │ │ ├── Screenshot_from_2014-05-08_01-56-27.png │ │ │ │ ├── si1ent.png │ │ │ │ └── tshirt-x360.png │ │ ├── silent_2.0 │ │ │ ├── README.md │ │ │ ├── WX20220927-173925.png │ │ │ └── WechatIMG533.png │ │ ├── timeline.md │ │ ├── vue-at │ │ │ ├── README.md │ │ │ ├── WechatIMG1.jpeg │ │ │ └── WechatIMG2.jpeg │ │ └── website-badge.svg │ ├── reports.md │ └── sidebar.md └── vendor │ ├── blog.css │ ├── blog.js │ ├── fork.png │ ├── github.png │ ├── highlight.pack.js │ ├── jquery-1.11.1.min.js │ ├── lodash-4.17.21.min.js │ ├── marked-0.5.0.min.js │ ├── mermaid-9.1.7.min.js │ ├── pace-1.2.4.min.js │ └── zenburn.css ├── package.json └── packages ├── create-silent ├── cli.js └── package.json └── silent ├── cli.js ├── index.js └── package.json /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['fritx/node', 'fritx/es2017'], 3 | ignorePatterns: [ 4 | 'packages/silent/blog/**' 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | pnpm-lock.yaml 4 | yarn.lock 5 | *.tgz 6 | 7 | packages/*/README.md 8 | packages/silent/blog 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "search.exclude": { 3 | "blog/vendor/*.{min,pack}.*": true, 4 | }, 5 | // https://github.com/antfu/eslint-config#config-vs-code-auto-fix 6 | // https://github.com/prettier/prettier-vscode#default-formatter 7 | "prettier.enable": false, 8 | "editor.formatOnSave": false, 9 | "editor.codeActionsOnSave": { 10 | "source.fixAll.eslint": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## Changelog 2 | 3 | - v0.1.2 (06/07) 4 | 1. fix resolve: ignore trailing slash 5 | 1. update font-family & code block style 6 | 1. upgrade gulp-deps & eslint 7 | 1. update readme 8 | 9 | - v0.1.1 (12/19) 10 | 1. no longer a cmd tool 11 | 1. no longer a node lib 12 | 1. update deps & fix eslint 13 | 1. recommend using prj to init 14 | 15 | - v0.1.0 (06/18) 16 | 1. fix local link target 17 | 1. no-semicolon style 18 | 19 | - v0.0.9-5 (06/02) 20 | 1. fix /usr/bin/env bug 21 | 1. use strict and eol 22 | 1. include dependencies gulp/eslint/eol 23 | 24 | - v0.0.9-4 (05/31) 25 | 1. set bg-color to white 26 | 1. sans-serif instead for pre/code 27 | 1. search for mainTitle in h1~h6 28 | 1. configurable container selectors 29 | 1. move to CHANGELOG.md 30 | 31 | - v0.0.9-3 (05/29) 32 | 1. add index.js for usage as local module 33 | 1. slashes vars in regex 34 | 1. support hash with local links 35 | 36 | - v0.0.9-2 (05/24) 37 | 1. fix empty resolved href by . 38 | 1. optional disqus() and comments() 39 | 1. better access for config() and start() 40 | 41 | - v0.0.9-1 (05/22) 42 | 1. remove space caused by \n in p tags 43 | 1. add path resolve against ../ or ./ 44 | 1. not reload on default page not found 45 | 46 | - v0.0.8 (05/20) 47 | 1. add optional disqus support 48 | 1. flag data-loaded for local saved page 49 | 1. use percentage for font-size instead of px 50 | 1. make sure target is a directory (cli) 51 | 52 | - v0.0.7 (05/12) 53 | 1. try font "Microsoft YaHei" for chinese on windows 54 | 1. add image holder for shared links (apps like wechat) 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2014 Fritz Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # silent 2.0 2 | 3 |        4 | 5 | 6 | 7 | > Be a silent, static blog 8 | 9 | for silent 1.0, check [this](https://github.com/fritx/silent/tree/1x) out 10 | 11 | ## 🎉🎉 silent's 10th Anniversary 12 | 13 | SilentPress: a CMS alternative to VitePress and WordPress. 200+LOC written in Go.
14 | https://github.com/fritx/silentpress 15 | 16 | -- for the 10th-anniversary of *silent*. silent and its simplicity was a once a culture, a spirit, and a memory of ____
17 | #silent #10YearsAnniversary #simplicity #opensource 18 | 19 | ## Features 20 | 21 | ### Old-school & Clean 22 | 23 | - [x] no MVVM frameworks (no vue, react, etc) 24 | - [x] no CCS frameworks 25 | - [ ] no jquery 26 | 27 | ### Static & Portable 28 | 29 | - [x] no node_modules (no dependencies, etc) 30 | - [x] no build systems (no gulp, webpack, etc) 31 | - [x] no extra build commands (no npm-run-build or -generate) 32 | - [x] no CI/CD required (github-actions can be optional) 33 | - [x] source code is all it needs to run 34 | - [x] npm-create tooling 35 | 36 | ### Writing, Focus and Visualization 37 | 38 | - [x] markdown 39 | - [x] [mermaid](https://mermaid-js.github.io/mermaid/) diagrams 40 | 41 | ### Extendable & Integration 42 | 43 | - [x] analytics: google, baidu, etc 44 | - [x] comment system: [disqus](https://disqus.com) +[cusdis](https://cusdis.com) +[giscus](https://giscus.app), etc 45 | - [ ] backend permission api 46 | 47 | ### Funny & Fancy & Performance 48 | 49 | - [x] prefer history.pushState api 50 | - [x] progress bar on top 51 | - [x] auto favicon (extracted from title) 52 | - [x] favicon dark mode 53 | - [ ] page-level dark mode 54 | 55 | 56 | 57 | 58 | 59 | ### Security & Stability 60 | 61 | - [x] responsive design 62 | - [x] prefer es5 and guarded with eslint 63 | - [ ] fallback on browser compatibility break 64 | - [ ] IE 6+ support (needs polyfill, etc) 65 | 66 | 67 | 68 | 69 | 70 | ## Usage 71 | 72 | ```sh 73 | # create it 74 | npm create silent 75 | # or 76 | npm i -g silent 77 | silent create 78 | 79 | # e.g. 80 | npm create silent ~/t/my-blog 81 | # >>> 82 | # copying /Users/fritx/.nvm/versions/node/v16.14.0/lib/node_modules/silent/blog 83 | # => /Users/fritx/t/my-blog 84 | # silent-create completed 85 | 86 | # serve it 87 | cd ~/t/my-blog 88 | npx serve . -p 3000 89 | # >>> 90 | # Serving! http://localhost:3000 91 | 92 | # deploy to your github pages? 93 | cd ~/t/my-blog 94 | git init 95 | git remote add origin git@github.com:fritx/silent.git 96 | npx gh-pages -d . 97 | # >>> 98 | # Published. https://fritx.github.io/silent/ 99 | ``` 100 | 101 | ## Browser Compatibility 102 | 103 | Status: no IE 104 | 105 | - [ ] no IE https://caniuse.com/?search=arr%20includes 106 | - [ ] no IE https://caniuse.com/?search=str%20includes 107 | - [ ] no IE https://caniuse.com/?search=builtin%20object%20assign 108 | - [ ] IE10+ https://caniuse.com/?search=console 109 | - [x] IE10+ https://caniuse.com/?search=pushstate 110 | - [ ] IE9+ https://caniuse.com/?search=date.now 111 | - [ ] IE9+ https://caniuse.com/?search=object.keys 112 | - [ ] IE9+ https://caniuse.com/?search=arr%20foreach 113 | - [ ] IE9+ https://caniuse.com/?search=querySelector 114 | - [ ] IE9+ https://caniuse.com/?search=css3%20selectors 115 | - [x] IE8+ https://caniuse.com/?search=scrollintoview 116 | 117 | mermaid: 118 | 119 | - [x] no IE / Safari 15.4+ https://caniuse.com/?search=structuredClone 120 | - [ ] no IE https://caniuse.com/?search=arrow%20function 121 | 122 | auto title favicon: 123 | 124 | - [x] no IE https://caniuse.com/?search=prefers-color-scheme 125 | - [x] IE10+ https://caniuse.com/?search=matchMedia 126 | - [ ] IE9+ https://caniuse.com/?search=canvas 127 | 128 | if using giscus: 129 | 130 | - [ ] no IE https://caniuse.com/?search=ResizeObserver 131 | - [ ] IE8+ https://caniuse.com/?search=postmessage 132 | - [ ] IE8+ https://caniuse.com/?search=localstorage 133 | 134 | ## Silent Fans 135 | 136 | > Thank you! 137 | 138 | - [ZhanZengyu's Blog](https://zhanzengyu.github.io/blog/) 139 | - [Meizhuo's Blog](https://meizhuo.github.io/blog/) 140 | - [Amen's Blog](https://linzx89757.github.io/blog/) 141 | - [Jayin's Blog](https://v1.jayinton.com/blog/) 142 | - [Derek's Blog](https://derekgame2013.github.io/blog/) 143 | - [Huang's Blog](https://huangruichang.github.io) 144 | - [Jason's Blog](https://jacsonlee.github.io/Blog/) 145 | - [Jayden's Blog](https://iamjayden.github.io) 146 | - [Fritx' Blog](https://blog.fritx.me/) 147 | 148 | ## More.. 149 | 150 | > Rather than a framework or library, silent is more like a spirit - a culture. (says Huang) 151 | 152 | - [The 10th Anniversary of *silent*...](https://x.com/fz_ux55200/status/1786274684541321639) 153 | - [SilentPress: CMS Alternative to VitePress and WordPress. 200LOC in Go](https://news.ycombinator.com/item?id=40234012) 154 | - [Silent One Year Old](https://fritx.github.io/silent/?2015/05/silent-one-year-old) 155 | - ~~[Silent T-Shirt](http://udz.com/silent)~~ 156 | 157 | 158 | -------------------------------------------------------------------------------- /blog/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | ignorePatterns: [ 4 | // TODO: it is known that mermaid breaks es5 5 | 'vendor/mermaid*', 6 | // lodash is probably okay for es5 7 | 'vendor/lodash-4.17*', 8 | // jquery <= 1.12 is safe for es5 9 | // https://jquery.com/browser-support/ 10 | 'vendor/jquery-1.11*' 11 | ], 12 | overrides: [ 13 | { 14 | files: 'vendor/**/*.js', 15 | extends: ['plugin:es/restrict-to-es5'] 16 | }, 17 | { 18 | files: 'vendor/blog.js', 19 | extends: ['fritx/browser', 'fritx/es5-loose'], 20 | globals: { 21 | mermaid: 'readonly', 22 | marked: 'readonly', 23 | hljs: 'readonly', 24 | Pace: 'readonly', 25 | _: 'readonly', 26 | $: 'readonly' 27 | }, 28 | rules: { 29 | 'no-mixed-operators': 0, 30 | 'no-unused-vars': 0 31 | } 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /blog/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/favicon.ico -------------------------------------------------------------------------------- /blog/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 43 | 44 |
45 |
46 |
47 | 48 | 49 |
50 |
51 |
52 |
53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 90 | 91 | 92 | 93 | 100 | 101 | 102 | 103 | 104 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /blog/p/2014/09/bug/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/09/bug/close.png -------------------------------------------------------------------------------- /blog/p/2014/09/bug/gulp-plugins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/09/bug/gulp-plugins.png -------------------------------------------------------------------------------- /blog/p/2014/09/bug/notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/09/bug/notification.png -------------------------------------------------------------------------------- /blog/p/2014/09/bug/reference.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/09/bug/reference.png -------------------------------------------------------------------------------- /blog/p/2014/09/bug/thanks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/09/bug/thanks.png -------------------------------------------------------------------------------- /blog/p/2014/09/gulp-eol-bug.md: -------------------------------------------------------------------------------- 1 | # 🐛 gulp-eol bugfix review 2 | 3 | *2014-09-06* 4 | 5 | ## 背景 6 | 7 | [gulp-eol][1]是我之前写的一个gulp插件,主要用于统一文件的换行符。 8 | 9 | 今早打开github,发现一俄国人跑来我这开[issue][2],说是复制/转移文件时,插件失效了,还贴出了他的gulpfile。 10 | 11 | 12 | 13 | 下午happy完回来,发现是自己程序的bug,修复后发布,并告知事主[@truetamtam][3]确认,tam很快说问题解决了,皆大欢喜。 14 | 15 | ## 我想说 16 | 17 | 凡事都应**以小见大**,这样才能进步成长。我列出了7点,不多。 18 | 19 | ### 1. 粗心大意 20 | 21 | 此bug乃低级错误: 22 | 23 | ```js 24 | str = str.replace(/\r?\n/g, eol); 25 | if (append && !( 26 | new RegExp(eol + '$').test(str)) 27 | ) { 28 | // this statement should be always executed 29 | // but not remained here 30 | file.contents = new Buffer(str + eol); 31 | } 32 | ``` 33 | 34 | 我错将一个关键的赋值逻辑放入了`if(){}`中,加之测试覆盖不全,导致bug埋藏许久。 35 | 36 | ### 2. 心存感激 37 | 38 | 整个issue下来,共6次发言,我和tam各3次。我们的发言基本上都带有感谢或友好。虽然这大多时候只是一种礼节,但我相信大家都是一样,发自内心地享受友爱和互助。 39 | 40 | 我甚至在[代码更新][4]中“慷慨激昂”地道谢: 41 | 42 | 43 | 44 | ### 3. 明于展示 45 | 46 | > Talk is cheap, show me the code! 47 | 48 | 相信大家都知道这句it界的名言,口说无凭,很多时候我们需要用代码、用实例来说明问题。在这一点上,我和tam都是做的不错的: 49 | 50 | - 问题提出时,他贴上了gulpfile,便于我对环境的了解 51 | - bug初步确定时,我给出了简短的源码注解(同1.),表达了自己的判断 52 | 53 | ### 4. 巧于引用 54 | 55 | 56 | 57 | bug修复后,在提交描述中提及issue的编号,如"#1",issue页会及时地追加一条标签。虽然这只是github一个简单的功能,但它发挥着关键作用: 58 | 59 | - 通知:及时明确地展示提交描述 60 | - 关联:精确链接到具体的代码改动 61 | - 简明:就具体的代码改动,你已无需额外发言阐述 62 | 63 | 另外,我用了"for #1",而不是"fix #1"。因为此bug与事主的实例并无绝对联系,当时只是初步判定,用"for"可以在引用issue的同时,不close掉它。 64 | 65 | ### 5. 堪称典范 66 | 67 | > 整个issue下来,共6次发言,我和tam各3次 68 | 69 | 是的,加上3次操作,共9步,让我们来回顾一下: 70 | 71 | 1. tam:提出问题,贴出实例 72 | 1. 我:表示迟点回应,感谢 73 | 1. 我:(发现有bug,贴上bug标签) 74 | 1. 我:表示已有初步判定,贴出注解,预告更新,感谢 75 | 1. tam:酷,感谢 76 | 1. 我:(提交更新,引用issue) 77 | 1. 我:告知已发布,要求确认 78 | 1. tam:表示确认,感谢 79 | 1. tam:(关闭issue) 80 | 81 | 82 | 83 | 别看这区区小issue,它包括了扼要的表达、精准的操作,包括了: 84 | 85 | 1. 提出议题,描述问题 86 | 1. 初步回应 87 | 1. 问题分类确定 88 | 1. 症结确定和描述 89 | 1. 预告更新 90 | 1. 更新提交和描述 91 | 1. 更新告知,要求确认 92 | 1. 问题解决确认 93 | 1. 关闭议题 94 | 95 | 这简直就是issue的标杆、模板与典范。感谢tam的配合。 96 | 97 | ### 6. 猜想成立 98 | 99 | 之前接触grunt/gulp这批新兴的构建工具,见识了琳琅满目的插件,加之web开发者的冲劲有目共睹,有了以下猜想: 100 | 101 | - 复制/编译/压缩/测试,还有什么gulp不能做? 102 | - gulp能做很多,将存在不少未开发甚至未知的插件 103 | - 发现并开发出来,有类似需求的人会主动来前来使用 104 | 105 | 短短几行代码,gulp-eol写好发布,未作任何推广,自己没用几次,几个月后竟有人“自投罗网”。事实证明,我的猜想是对的。 106 | 107 | 108 | 109 | ### 7. 关于github 110 | 111 | 在同学之中,[我在github](https://github.com/fritx)上的活跃度和“功绩”应属最佳。这得益于web开发者(尤其是web前端)一贯的开源氛围。 112 | 113 | 以前是我找老外,提issue,现在也逐渐变成了他们找我。非常享受跟他们一起交流学习。当然,与国人、同学也是一样。 114 | 115 | github能给你以“虚荣”: 116 | 117 | - “嘿,npm排行第2的aysnc库,我可是[top6/89][5]的贡献者。” 118 | - “用过zepto?” “不但用过,还参与开发,[top68/151][6]。” 119 | 120 | github虽不是全部,但也是一种角度。据我所知,不少it公司,包括我们公司,都非常重视应聘者的github。多点使用github,尽可能开采它的功能吧。Just for fun! 121 | 122 | ## 结语 123 | 124 | 想提升**吹牛技艺**的可以联系本人。 125 | 126 | 注意,全文并未提及“装B”二字。 127 | 128 | [1]: https://github.com/fritx/gulp-eol 129 | [2]: https://github.com/fritx/gulp-eol/issues/1 130 | [3]: https://github.com/truetamtam 131 | [4]: https://github.com/fritx/gulp-eol/commit/86018672a37cfaa49ebb7f7c20bf9136b0add43a 132 | [5]: https://github.com/caolan/async/graphs/contributors 133 | [6]: https://github.com/madrobby/zepto/graphs/contributors 134 | -------------------------------------------------------------------------------- /blog/p/2014/10/QQ图片20141022210533.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/10/QQ图片20141022210533.jpg -------------------------------------------------------------------------------- /blog/p/2014/10/QQ图片20141022210537.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/10/QQ图片20141022210537.jpg -------------------------------------------------------------------------------- /blog/p/2014/10/QQ图片20141022214120.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2014/10/QQ图片20141022214120.jpg -------------------------------------------------------------------------------- /blog/p/2014/10/free-your-html-body-tags.md: -------------------------------------------------------------------------------- 1 | # Free your html/body tags 2 | 3 | *2014-10-23* 4 | 5 | Today my leader asked me why the topbar on mobile [Qiushibaike](https://qiushibaike.com) covered page contents, while it should not. 6 | 7 | 8 |    9 | 10 | 11 | I quickly looked into the problem, with the git log showed no big deals, I suddenly found it was a line of css that had been unexpectedly overwriten. 12 | 13 | 14 | 15 | Finally, leader pointed out it was an external script, probably advertisement stuff, that produced such nonsense css code which overwrites. A quick solution though, is to add an `!important` flag. 16 | 17 | With complaint of those evil external scripts, we had also noticed our abuse on `` tag. These tags should not be **over-depended** any more, while they are usually of easy accesses. 18 | 19 | So, free your html and body tags! Make sure you have a `.container` stuff or someting. 20 | -------------------------------------------------------------------------------- /blog/p/2014/12/test-on-javascript.md: -------------------------------------------------------------------------------- 1 | # 🔧 Test on JavaScript 2 | 3 | *2014/12/27* 4 | 5 | > A talk at WYU Dev Conf 🎤 6 | 7 | 8 | ## Assertion Libraries 9 | 10 | - Expect 11 | - Should 12 | - Assert 13 | 14 | ### Expect 15 | 16 | ```js 17 | expect(window.r).to.be(undefined); 18 | expect({ a: 'b' }).to.eql({ a: 'b' }); 19 | expect(5).to.be.a('number'); 20 | expect([]).to.be.an('array'); 21 | expect(window).not.to.be.an(Image); 22 | ``` 23 | 24 | ### Should 25 | 26 | ```js 27 | user.should.have.property('name', 'tj'); 28 | user.should.have.property('pets').with.lengthOf(4); 29 | // Object.create(null) 30 | should(user).have.property('name', 'tj'); 31 | should(true).ok; 32 | ``` 33 | 34 | ### Assert 35 | 36 | ```js 37 | assert.ok(5 === 5) 38 | assert.equal(err, null) 39 | assert.strictEqual(5, 5) 40 | assert.deepEqual({ a: 'b' }, { a: 'b' }) 41 | assert.throws(badFn, Error) 42 | ``` 43 | 44 | 45 | ## Stubs 46 | 47 | - Chance 48 | - Faker 49 | - Sinon 50 | 51 | ### Chance 52 | 53 | ```js 54 | chance.bool(); 55 | //=> true 56 | chance.integer(); 57 | //=> -1293235 58 | chance.string(); 59 | //=> 'Z&Q78&fqkPq' 60 | chance.color() 61 | //=> '#79c157' 62 | chance.ip() 63 | //=> '153.208.102.234' 64 | ``` 65 | 66 | ### Sinon 67 | 68 | ```js 69 | function getTodos(listId, callback) { 70 | jQuery.ajax({ 71 | url: "/todo/" + listId + "/items", 72 | success: function (data) { 73 | // Node-style CPS: callback(err, data) 74 | callback(null, data); 75 | } 76 | }); 77 | } 78 | sinon.stub(jQuery, "ajax"); 79 | getTodos(42, sinon.spy()); 80 | 81 | assert( 82 | jQuery.ajax.calledWithMatch({ url: "/todo/42/items" }) 83 | ); 84 | jQuery.ajax.restore(); 85 | ``` 86 | 87 | ```js 88 | var clock = sinon.useFakeTimers(); 89 | $el.animate({ height: "200px", width: "200px" }, 500); 90 | 91 | clock.tick(510); 92 | assertEquals("200px", $el.css("height")); 93 | assertEquals("200px", $el.css("width")); 94 | ``` 95 | 96 | 97 | ## Runners 98 | 99 | - QUnit 100 | - NodeUnit 101 | - Jasmine 102 | - Mocha 103 | 104 | ### Jasmine 105 | 106 | ```js 107 | describe('AsyncProcess', function() { 108 | var asyncProcess; 109 | beforeEach(function() { 110 | asyncProcess = new AsyncProcess(); 111 | }); 112 | 113 | it('should process 42', function() { 114 | var done = false; 115 | var processed = null; 116 | 117 | deferred = asyncProcess.process(); 118 | deferred.then(function(result) { 119 | done = true; 120 | processed = result; 121 | }); 122 | 123 | waitsFor(function() { 124 | return done; 125 | }, "the async process to complete", 10000); 126 | 127 | runs(function() { 128 | expect(processed).toEqual(42); 129 | }); 130 | }); 131 | }); 132 | ``` 133 | 134 | ### Mocha 135 | 136 | ```js 137 | describe('AsyncProcess', function() { 138 | var asyncProcess; 139 | beforeEach(function() { 140 | asyncProcess = new AsyncProcess(); 141 | }); 142 | 143 | it('should process 42', function(done) { 144 | deferred = asyncProcess.process(); 145 | 146 | deferred.then(function(processed) { 147 | processed.should.be.equal(42); 148 | done(); 149 | }); 150 | }); 151 | }); 152 | ``` 153 | 154 | 155 | ## Environments 156 | 157 | - Node 158 | - Real Browsers 159 | - Karma 160 | - Phantom 161 | - Casper 162 | - Nightmare 163 | 164 | ### Phantom 165 | 166 | ```html 167 | 168 | 169 | Tests 170 | 171 | 172 | 173 |
174 | 175 | 176 | 181 | 182 | 186 | 187 | 188 | ``` 189 | 190 | 191 | ## References 192 | 193 | - 五个值得尝试的前端开发工具 https://www.leiphone.com/news/201406/5-great-front-end-dev-tools.html 194 | 195 | - 使用Karma来驱动mocha测试 https://www.shenyanchao.cn/blog/2013/03/27/use-karma-to-run-mocha-test/ 196 | 197 | - 单元测试之Stub和Mock https://www.cnblogs.com/TankXiao/archive/2012/03/06/2366073.html 198 | 199 | 200 | ## Thanks 201 | 202 | - [WYU Dev Conf][1] & [互诺科技][2] 203 | - [Jayin Ton][3] & [Jason Lee][4] 204 | 205 | 206 | ## Author 207 | 208 | @fritx; Powered by the [Silent][5] Blog 209 | 210 | [1]: https://wuyiuniversity.github.io/ 211 | [2]: https://baike.baidu.com/item/互诺科技/7246160 212 | [3]: https://github.com/Jayin 213 | [4]: https://github.com/jacsonLee 214 | [5]: ../../projects/silent_2.0/ 215 | -------------------------------------------------------------------------------- /blog/p/2015/01/fs-auth.md: -------------------------------------------------------------------------------- 1 | # Why I built fs-auth and how it works 2 | 3 | *2015-01-11* 4 | 5 | Several days ago I created a tool, which was named [fs-auth](https://github.com/fritx/fs-auth) and titled "auth beyond filesystem". That was an early idea. 6 | 7 | 1. In the beginning, I wanted to upload projects onto Github, with some sensitive files included (inappropriate but convinient, though), such as **connection config** or **password stuff**. 8 | 1. Later on, I wanted to encrypt, you know, some **personal files**. 9 | 1. Recently, I wanted to implement a file-based db (something like [lowdb](https://github.com/typicode/lowdb)), but with **user authentication**. 10 | 11 | But I'd never figured out a way that is flat and straightforward, until fs-auth: 12 | 13 | - encrypts files with passwords given 14 | - auths and decrypts files with correct passwords 15 | - fails auth with incorrect passwords 16 | 17 | ![overview](fs-auth/overview.png) 18 | 19 | ## So how does it work? 20 | 21 | Here are our needs: 22 | 23 | 1. With a password required, original files get encrypted. 24 | 2. Encrypted files could verify the correct password. 25 | 3. With the correct password, encrypted files could be decrypted. 26 | 4. The password could not be figured out from encrypted files. 27 | 5. Even with original files, the password could not be figured out. 28 | 29 | ### Password Verification 30 | 31 | We **hash the password** and prepend it to the encrypted file, for later verification. 32 | 33 | ![auth](fs-auth/auth.png) 34 | 35 | Note that barely md5 is not safe enough. We use **combinations** of md5 and sha1 instead. 36 | 37 | ### Contents Encrypting/Decrypting 38 | 39 | While encrypting, we shift each bit (simply increase its value) of file contents, using **another hash of the password** as key. While decrypting, we unshift (decrease) it. 40 | 41 | ![shift](fs-auth/shift.png) 42 | 43 | ## Entire Flows 44 | 45 | ### File Locking 46 | 47 | ![encrypt](fs-auth/encrypt.png) 48 | 49 | ### File Auth 50 | 51 | ![decrypt](fs-auth/decrypt.png) 52 | -------------------------------------------------------------------------------- /blog/p/2015/01/fs-auth/auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/01/fs-auth/auth.png -------------------------------------------------------------------------------- /blog/p/2015/01/fs-auth/decrypt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/01/fs-auth/decrypt.png -------------------------------------------------------------------------------- /blog/p/2015/01/fs-auth/encrypt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/01/fs-auth/encrypt.png -------------------------------------------------------------------------------- /blog/p/2015/01/fs-auth/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/01/fs-auth/overview.png -------------------------------------------------------------------------------- /blog/p/2015/01/fs-auth/shift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/01/fs-auth/shift.png -------------------------------------------------------------------------------- /blog/p/2015/01/why-no-semicolon.md: -------------------------------------------------------------------------------- 1 | # Why I don't write a semi 2 | 3 | *2015-01-07* 4 | 5 | I've been asked for several times why I don't write down a semicolon, after each statement in my JavaScript. 6 | 7 | Most of the time it doesn't even worth a word to answer. In other words, I can't find any reason to do that anymore. 8 | 9 | Yes, in languages like Java even PHP, semicolons are required. But in JavaScript, they are **optional**. 10 | 11 | The below are the reasons why I finally switched to the no-semicolon style: 12 | 13 | 1. It saves effort 14 | 15 | Why do I bother myself to type while I don't have to? 16 | 17 | 1. Code becomes clear 18 | 19 | Semicolons are such irrelevant stuff. Also, a newline already indicates a break. 20 | 21 | 1. It is **npm** Coding Style 22 | 23 | See *Semicolons* Section [here](https://docs.npmjs.com/misc/coding-style) for more 24 | 25 | 1. It is reliable and applied 26 | 27 | Not like that unreliable as argued somewhere, actually it's been applied in some popular projects, from backend to frontend such as [npm/npm](https://github.com/npm/npm), [request/request](https://github.com/request/request), [madrobby/zepto](https://github.com/madrobby/zepto), [yyx990803/vue](https://github.com/yyx990803/vue). 28 | 29 | No-semicolon style does not mean "no semicolon at all", instead, it means "write only when required". Do not forget to prepend a semicolon for those lines with leading `(`, `[`, `/`, `+`, `-`. 30 | 31 | Here is [another article](https://mislav.net/2010/05/semicolons/), by Mislav, stuff in Github. 32 | -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/chang.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/chang.jpg -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/derek.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/derek.jpg -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/index.md: -------------------------------------------------------------------------------- 1 | # 🎉 silent one year old 2 | 3 | *2015-05-09* 4 | 5 | > silent不是我在github的第一个项目,但绝对是生命力最持久,收获眼球最多的一个。 6 | 7 | ![si1ent](../../../projects/silent/pic/si1ent.png) 8 | 9 | (Designed by: **@huangruichang**) 10 | 11 | [silent](.././../../projects/silent/)是什么?**silent是一款极简的轻量级静态博客框架**,拥有自己的一套载入机制和“哲学”。 12 | 13 | silent开启了我的极简主义之路,从此一发不可收拾,我的大脑无法再接收复杂的东西。 14 | 15 | 可以说,silent伴我走过了大学里几乎是最后的一段时光,充满艰辛和回味的一年,始终和我一同成长着。从最初的宿舍楼范围内的苦力推销,到如今我欣慰地看到,silent思想被越来越多的人接纳和传扬。 16 | 17 | 18 | 19 | 那么,就让我们回顾一下silent的历程吧: 20 | 21 | 去年5月8日,我发布了[silent][1]的第一个版本,还有我自己的博客([fritx.github.io/blog][3]) 22 | 23 | 5月9日,**@IamJayden**同学使用silent搭建了博客([IamJayden.github.io][4]) 24 | 25 | 5月14日,**@jacsonLee**同学使用silent搭建了博客([jacsonLee.github.io/Blog][5]) 26 | 27 | 5月19日,**@huangruichang**同学使用silent搭建了博客([huangruichang.github.io][6]) 28 | 29 | 5月24日,路人**@7c00**使用silent搭建了博客([7c00.github.io/b14][9]),并一度对silent进行了客观评价(值得思考) 30 | 31 | 9月11日,同事**@Derekgame2013**使用silent搭建了博客([Derekgame2013.github.io/blog][7]) 32 | 33 | 10月14日,**@Jayin**同学发布了silent的又一分支[silentor][2],搭建了博客([Jayin.github.io][8]),助力silent传承。 34 | 35 | 非常感谢,silent与你同在! 36 | 37 | 47 | 48 |    49 | 50 |    51 | 52 |    53 | 54 |    55 | 56 |    57 | 58 | 59 | 其实silent这个词(静默),跟我本人有着很大的对比。我有着一个高调的、热衷于装逼的性格。我时常为了点技术的事跟人争得不可开交,我还时常急于把尚不明确的点子与人分享,每写出一点代码,我就会大肆宣扬,巴不得所有人都看见。 60 | 61 | 但正是这种狂傲不羁的性格,驱使着我在开源的道路上不断前行。到现在,[我在github][10]已经发布了58份代码,收获57颗星,29次fork。装逼无罪,如果你足够热爱,那么请你尽情释放,做张扬的自己。 62 | 63 | 然而眼下,有那么一些事情正等着我去做,我知道,有些机会我必须把握。如果一些事情对你来说非常重要,那么也请你低调地把它做好!我是林亮,我为silent代言。 64 | 65 | [1]: https://github.com/fritx/silent 66 | [2]: https://github.com/Meizhuo/silentor 67 | [3]: https://fritx.github.io/blog/ 68 | [4]: https://IamJayden.github.io 69 | [5]: https://jacsonLee.github.io/Blog/ 70 | [6]: https://huangruichang.github.io 71 | [7]: https://Derekgame2013.github.io/blog/ 72 | [8]: https://Jayin.github.io 73 | [9]: https://7c00.github.io/b14/ 74 | [10]: https://github.com/fritx 75 | -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/jacson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/jacson.jpg -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/jayden.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/jayden.png -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/jayin.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/jayin.jpg -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/silent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/silent.png -------------------------------------------------------------------------------- /blog/p/2015/05/silent-one-year-old/todd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2015/05/silent-one-year-old/todd.gif -------------------------------------------------------------------------------- /blog/p/2016/08/silent-talk.md: -------------------------------------------------------------------------------- 1 | # silent talk 2 | 3 | *2016-08-02* 4 | 5 | > 装逼无罪,如果你足够热爱,那么请你尽情释放,做张扬的自己 6 | 7 | Hello大家好,我是亮爷。今天给大家带来的是,一个静态博客框架,[silent](../../projects/silent_2.0/)。S-I-L-E-N-T,安静、静默的意思。为什么用这个名字呢?主要是因为当时,好的单词都被注册完了吧,哈哈。 8 | 9 | silent出生于2014年5月份,和我一样都是金牛座。 10 | 11 | 那么,silent到底有多静态呢? 12 | 13 | 我们翻开silent的github链接,Features部分写道: 14 | 15 | 1. Markdown让写作更简洁、更专注 16 | 17 | 和大多数博客框架一样,silent迎合主流的markdown写作方式。 18 | 19 | 2. 灵活的页面管理机制,文件结构自由设定 20 | 21 | 一切皆页面。包括边栏、主体,所有独立显示的区域,都被视为文章页面,并且对应到文件系统里。你可以自行整理,然后调整链接指向即可。 22 | 23 | 3. 代码精简,体积轻量,没多少东西 24 | 25 | 与jekyll不同,你可以任意书写markdown并且为其命名。与hexo不同,你无须生成多余的文件并且上传。 26 | 27 | silent会运行时加载解释markdown,所以发布时没有多余的generate操作。 28 | 29 | 对于silent来说,只有基础的几个文件,以及文章对应的markdown文件有必要上传到服务器,非常容易部署。 30 | 31 | 4. 响应式,各屏幕尺寸正常显示 32 | 33 |
34 | 35 | 36 | silent不仅仅是框架,同时也是一个极简博客模板,任何人都可以沿用这种思路,改造为更适合自己的blog框架。英爷的[silentor](https://github.com/Jayin/silentor)就是一个非常棒的例子。 37 | 38 | 对了,去年silent一周年的时候,我们还特地为silent用户定制了Tshirt,silent的主题色是灰黑色。 39 | 40 | 引用定制Tshirt时写下的一段话: 41 | 42 | > silent是一款极简的轻量级静态博客框架
43 | “装逼无罪,如果你足够热爱,那么请你尽情释放,做张扬的自己。”
44 | 我们希望更多的人加入进来,接纳silent思想,传承silent文化 45 | 46 | 额,为什么叫每日一秀呢?主要是比较好听。我想以我的能力,应该没办法办到吧。除非,除非你换一种方式来理解这个名字?嘿嘿。如果有朋友愿意加入,那就再好不过了,哈哈。 47 | -------------------------------------------------------------------------------- /blog/p/2016/08/屏幕快照 2016-08-02 下午5.46.40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2016/08/屏幕快照 2016-08-02 下午5.46.40.png -------------------------------------------------------------------------------- /blog/p/2016/08/屏幕快照 2016-08-02 下午6.35.12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2016/08/屏幕快照 2016-08-02 下午6.35.12.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-134112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-134112.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-134431.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-134431.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-155434.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-155434.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-160316.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-160316.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-164233.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-164233.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-164651.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-164651.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220927-222427.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220927-222427.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220928-175618.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220928-175618.png -------------------------------------------------------------------------------- /blog/p/2022/09/WX20220928-180550.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/2022/09/WX20220928-180550.png -------------------------------------------------------------------------------- /blog/p/2022/09/blog-setup-via-github-fork.md: -------------------------------------------------------------------------------- 1 | # 🚀 Blog Setup via Github Fork 2 | 3 | *2022/09/27* 4 | 5 | > We chose [silent](../../projects/silent_2.0/), a static blog template, for example 6 | 7 | Note: If you know Git and Github well, [silent usage](?projects/silent_2.0/#usage) can be what you need 8 | 9 | Otherwise, if you're a beginner, then here we go: 10 | 11 | 1. Go to silent homepage: https://github.com/fritx/silent 12 | 13 | 2. Click `Fork` at the top right corner 14 | 15 | 16 | 17 | 3. Rename the repo, a brief name `blog` is recommended 18 | 19 | The repo name is important 'cause it is part of the final **BLOG URL** you're gonna get, like 20 | 21 | ```plain 22 | https://.github.io// 23 | ``` 24 | 25 | e.g., https://h5lium.github.io/blog/ 26 | 27 | 4. Don't forget to turn off the checkbox `Copy the xxx branch only` 28 | 29 | 30 | 31 | 5. Click `Create fork` at the bottom 32 | 33 | 6. (Important) Select both `gh-pages` and `/ (root)` in `Project Settings -> Pages` 34 | 35 | 36 | 37 | ... and **YOU'RE DONE!** 🎉 Try `https://.github.io//` in a few seconds. 38 | 39 | e.g., https://h5lium.github.io/blog/ 40 | 41 | 7. (Optional) Switch the default branch to `gh-pages` in `Project Settings -> Branches` 42 | 43 | 44 | 45 | 8. Update the `About` section, replace the description and link with your own ones 46 | 47 | ... so that everyone can give it a try! 🌏 48 | 49 | 50 | 51 | ## ... but How do I add a post? 52 | 53 | 1. First of all, you need to understand a bit of **Markdown**, and its syntax 54 | 55 | See examples in https://en.wikipedia.org/wiki/Markdown 56 | 57 | 1. Head to the `p/` directory, where all the blog contents are listed 58 | 59 | e.g., https://github.com/h5lium/blog/tree/gh-pages/p 60 | 61 | 62 | 63 | 2. Create a post by clicking `Add file`, for example, `p/2022/09/my-first-post.md` with some contents: 64 | 65 | ```diff 66 | 67 | 68 | +# 😁 My First Post 69 | + 70 | +> Hello World! 71 | + 72 | +bla bla bla... 73 | ``` 74 | 75 | 3. Open one of the index pages, for example, `p/posts.md`, and click the ✏️ (edit button) 76 | 77 | ... and then add a corresponding link and a digest, like: (a relative path is required) 78 | 79 | ```diff 80 | 81 | 82 | # 🌈 My Posts 83 | 84 | +## [My First Post](2022/09/my-first-post.md) 85 | + 86 | +> Hello World! 87 | 88 | ## [Blog Setup via Github Fork](2022/09/blog-setup-via-github-fork.md) 89 | ... 90 | ``` 91 | 92 | 93 | 94 | ... now a new post gets published! 🚀 95 | 96 | **References:** 97 | 98 | - [开启你的个人博客之旅](https://github.com/hey-q/blog#readme) 99 | - [1分钟快速构建你的博客](https://v1.jayinton.com/silentor/?p=docs/getting-start/main.md) 100 | - [silentor, a friendly fork of silent](https://v1.jayinton.com/silentor/) 101 | - https://github.com/Jayin/silentor 102 | - https://github.com/fritx/silent 103 | - [silent 2.0](../../projects/silent_2.0/) 104 | - [silent 1.0-legacy](../../projects/silent/) 105 | - [silent talk](../../2016/08/silent-talk.md) 106 | -------------------------------------------------------------------------------- /blog/p/2022/09/wtf-is-that-mac-icloud-handoff-en.md: -------------------------------------------------------------------------------- 1 | # 😡 What the \* is that! 🍎iCloud's "Hand off a webpage between devices"? 2 | 3 | > No longer to worry that 🔞 pages I'm browsing is being sent to the iPad 4 | 5 | *#Apple #iCloud #iPad #Mac #Handoff #Security #Privacy* 6 | 7 | *2022-09-28* 8 | 9 | [简体中文](./wtf-is-that-mac-icloud-handoff.md) | English 10 | 11 | 12 | 13 | I seldom use iPad myself, so when I face it I got totally shocked 😱 14 | 15 | Imagine this: 16 | 17 | > You're browsing some 🔞 secrets in your Mac 18 | 19 | > and one of your family members just happens to use your iPad (with the same AppleID) 20 | 21 | > iPad is gonna show an access to that page 😲, without any permission 22 | 23 | > even if you're using Chrome! not only for Safari 24 | 25 | so Apple never cares about privacy and security (for this scenario)? 26 | 27 | so What the F**k is that! 28 | 29 | ### Concerns about Privacy and Security 30 | 31 | We all know that Apple's iCloud syncing can be insecure (like the "Photo Syncing") 32 | 33 | so I've been always keeping the risk under control 34 | 35 | for example, I have "Photo Syncing" off in Apple devices, and use Android phones 36 | 37 | Everything was going well, until this * refreshed my view! 38 | 39 | ### How to solve it? 40 | 41 | I tried turning off "Safari Syncing" in iCloud, but it didn't work 42 | 43 | When I searched for the keywords "ipad safari can view mac", I found: 44 | 45 | > **See the webpages open on your other devices in Safari on Mac -- _Safari User Guide_**
46 | > https://support.apple.com/guide/safari/see-the-webpages-open-on-your-other-devices-sfri40726/mac 47 | 48 | > **Pick up where you left off with Handoff on Mac -- _macOS User Guide_**
49 | > https://support.apple.com/guide/mac-help/hand-off-tasks-between-devices-mchl732d3c0a/mac 50 | 51 | and what exactly "Handoff" [is](https://support.apple.com/en-us/HT209455): 52 | 53 | > **Use Handoff to continue tasks on your other devices**
54 | > With Handoff, you can start work on one device,
55 | > then switch to another nearby device and pick up where you left off. 56 | 57 | I finally figured out what the hell 👻 was that, and how to solve it 58 | 59 | ### Turn "Handoff" on or off 60 | 61 | > - On your Mac: Choose Apple menu > System Preferences, click General , then select “Allow Handoff between this Mac and your iCloud devices” (at the bottom of the pane). To turn it off, deselect the option. 62 | > - On iPad, iPhone, or iPod touch: Go to Settings > General > AirPlay & Handoff, then turn Handoff on or off. 63 | > - On Apple Watch: Open the Apple Watch app on iPhone, go to My Watch > General, then turn Enable Handoff on or off. 64 | 65 | So in your Mac, click on the top left corner 66 | 67 | choose "System Preferences" > "General", and turn off this "Handoff" shit 💩 68 | 69 | ![](WX20220928-175618.png) 70 | -------------------------------------------------------------------------------- /blog/p/2022/09/wtf-is-that-mac-icloud-handoff.md: -------------------------------------------------------------------------------- 1 | # 😡 什么神仙功能!🍎iCloud 的“接力”功能:“在设备之间传送网页”? 2 | 3 | > 妈妈再也不用担心,我正在浏览的🔞网页被传送到iPad上了 4 | 5 | *#苹果 #Apple #iCloud #iPad #Mac #接力 #Handoff #信息安全 #个人隐私* 6 | 7 | *2022-09-28* 8 | 9 | 简体中文 | [English](./wtf-is-that-mac-icloud-handoff-en.md) 10 | 11 | 12 | 13 | 我自己平时很少使用iPad,但当我发现这个问题时我震惊了 😱 14 | 15 | 设想一下: 16 | 17 | > 你在Mac上正在浏览的是 🔞 网页,在iPad屏幕的右下角会有提示,并且可以直接打开 18 | 19 | > 你的家人碰巧在使用你的iPad(登录着相同的AppleID) 20 | 21 | > iPad右下角会提示,并且能够一键打开你正在浏览的网页 😲 22 | 23 | > 甚至是你日常使用的Chrome!Safari以外的浏览器,依然无法幸免 24 | 25 | 这就来到了文章的标题:😡 **这是什么神仙功能!What the Hell is that?!** 26 | 27 | ### 个人隐私安全 28 | 29 | 虽说早有耳闻苹果iCloud同步本身就不安全(如相片同步) 30 | 31 | 所以iCloud同步方面的个人隐私风险我早有控制(通过合理配置,结合个人日常使用方式) 32 | 33 | 比如我是关闭了相片同步,日常使用的是Android手机+Mac电脑,基本没有问题 34 | 35 | ### 如何解决 36 | 37 | 尝试过关闭iCloud同步中的“Safari数据”,无法解决 38 | 39 | 当我搜索"ipad safari can view mac",终于得到了想要的结果 40 | 41 | > **在 Mac 上的 Safari 浏览器中查看在其他设备上打开的网页 - 42 | 《Safari 浏览器使用手册》**
43 | > https://support.apple.com/zh-cn/guide/safari/sfri40726/mac 44 | 45 | > **在 Mac 上使用“接力”回到上次离开的地方 - 46 | 《macOS 使用手册》**
47 | > https://support.apple.com/zh-cn/guide/mac-help/mchl732d3c0a/mac 48 | 49 | 以及“接力”这个功能的[正式介绍](https://support.apple.com/zh-cn/HT209455): 50 | 51 | > **使用接力在其他设备上继续完成任务**
52 | > 借助接力,您可以在一台设备上开始工作,再切换到附近的另一台设备上继续工作。 53 | 54 | 阅读完相关文档后,终于弄清楚了这是个什么鬼👻,以及如何解决 55 | 56 | ### 打开或关闭“接力” 57 | 58 | > - 在您的 Mac 上:选取苹果菜单 >“系统偏好设置”,点按“通用” ,然后选择“允许在这台 Mac 和 iCloud 设备之间使用接力”(位于面板底部)。若要将其关闭,请取消选择该选项。 59 | > - 在 iPad、iPhone 或 iPod touch 上:前往“设置”>“通用”>“隔空播放与接力”,然后打开或关闭“接力”。 60 | > - 在 Apple Watch 上:在 iPhone 上的 Apple Watch App 中,前往“我的手表”>“通用”,然后打开或关闭“启用接力”。 61 | 62 | 在Mac点击左上角,打开“系统设置”>“通用“,关闭这个什么狗屁 “接力”(“Handoff”)💩 63 | 64 | ![](WX20220928-175618.png) 65 | -------------------------------------------------------------------------------- /blog/p/aboutme.md: -------------------------------------------------------------------------------- 1 | # 😅 About Me 2 | 3 | ## Fritz Lin 4 | 5 | avatar 6 | 7 | > Life is short, I use JS 8 | 9 | ## Skills 10 | 11 | - Node.js / JavaScript Programming 12 | - Website Design (CSS / HTML) 13 | 14 | ## On Github 15 | 16 | 17 |

18 | [@fritx](https://github.com/fritx)  ![](https://img.shields.io/github/stars/fritx?style=social) 19 |

20 | 21 | ## Blog powered by 22 | 23 | An Entire Static Blog Framework: [silent](projects/silent_2.0/) 24 | -------------------------------------------------------------------------------- /blog/p/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/avatar.jpg -------------------------------------------------------------------------------- /blog/p/posts.md: -------------------------------------------------------------------------------- 1 | # 🌈 My Posts 2 | 3 | ## [😡 What the \* is that! 🍎iCloud's "Hand off a webpage between devices"?](2022/09/wtf-is-that-mac-icloud-handoff-en.md) 4 | 5 | > No longer to worry that 🔞 pages I'm browsing is being sent to the iPad 6 | 7 | ## [🚀 Blog Setup via Github Fork](2022/09/blog-setup-via-github-fork.md) 8 | 9 | > We chose silent, a static blog template, for example 10 | 11 | ## [silent talk](2016/08/silent-talk.md) 12 | 13 | > 装逼无罪,如果你足够热爱,那么请你尽情释放,做张扬的自己 14 | 15 | ## [🎉 silent one year old](2015/05/silent-one-year-old/) 16 | 17 | > silent不是我在github的第一个项目,但绝对是生命力最持久,收获眼球最多的一个 18 | 19 | ## [Why I built fs-auth and how it works](2015/01/fs-auth.md) 20 | 21 | > But I'd never figured out a way that is flat and straightforward 22 | 23 | ## [Why I don't write a semi](2015/01/why-no-semicolon.md) 24 | 25 | > I've been asked for several times why I don't write down a semicolon 26 | 27 | ## [🔧 Test on JavaScript](2014/12/test-on-javascript.md) 28 | 29 | > A talk at WYU Dev Conf 🎤 30 | 31 | ## [Free your html/body tags](2014/10/free-your-html-body-tags.md) 32 | 33 | > Today my leader asked me why the topbar on mobile 34 | 35 | ## [🐛 gulp-eol bugfix review](2014/09/gulp-eol-bug.md) 36 | 37 | > 凡事都应以小见大,这样才能进步成长。我列出了7点,不多 38 | -------------------------------------------------------------------------------- /blog/p/projects/github-badge.svg: -------------------------------------------------------------------------------- 1 | github: devgithubdev -------------------------------------------------------------------------------- /blog/p/projects/gitter-badge.svg: -------------------------------------------------------------------------------- 1 | gittergitterjoin chatjoin chat -------------------------------------------------------------------------------- /blog/p/projects/index.md: -------------------------------------------------------------------------------- 1 | # 🎯 Projects that I worked in 2 | 3 | ## [📅 Projects timeline](timeline.md) 4 | 5 | > All my projects on Github 6 | 7 | ## [silent 2.0](silent_2.0/) 8 | 9 | > Be a silent, static blog 10 | 11 | ## [✋🏻 react-drag-sizing](react-drag-sizing/) 12 | 13 | > "Drag to resize" (sizing) as React Component. 14 | 15 | ## [👨‍👩‍👧‍👦 vue-at](vue-at/) 16 | 17 | > At.js for Vue. 18 | 19 | ## [silent 1.0-legacy](silent/) 20 | 21 | > Be a silent, static blog 22 | -------------------------------------------------------------------------------- /blog/p/projects/react-drag-sizing/README.md: -------------------------------------------------------------------------------- 1 | # ✋🏻 react-drag-sizing 2 | 3 |    4 |    5 | 6 | 7 | 8 | - [x] "Drag to resize" (sizing) as React Component 9 | - [x] Rewritten with TS & React-hooks 10 | - [ ] Polyfill workaround with React < 16.8 11 | - [x] Support both mouse & touch 12 | - [x] Rollup bundle for both esm & umd 13 | - [x] Default handlerWidth=16, handlerOffset=-w/2, handlerZIndex=10 14 | - [x] Legacy branch: https://github.com/fritx/react-drag-sizing/tree/legacy 15 | - [x] Live Demo: https://fritx.github.io/react-drag-sizing 16 | 17 | ```sh 18 | npm i -S react-drag-sizing 19 | ``` 20 | 21 | ```tsx 22 | import DragSizing from 'react-drag-sizing' 23 | 24 |
25 |
26 |
27 | 28 | 29 | 30 | 31 |
32 |
33 | 34 | 35 | 36 |
37 |
38 | ``` 39 | 40 | #### Props 41 | 42 | ```tsx 43 | export type MEvent = MouseEvent | TouchEvent; 44 | export type RdsMEvent = 45 | | MouseEvent 46 | | (TouchEvent & { 47 | clientX: number; 48 | clientY: number; 49 | }); 50 | 51 | export interface DragSizingProps { 52 | border: 'top' | 'bottom' | 'left' | 'right'; 53 | onStart?: (e: RdsMEvent) => void; 54 | onEnd?: (e: RdsMEvent) => void; 55 | onUpdate?: (e: RdsMEvent) => void; 56 | id?: string; 57 | className?: string; 58 | style?: React.CSSProperties; 59 | handlerClassName?: string; 60 | handlerStyle?: React.CSSProperties; 61 | handlerWidth?: number; 62 | handlerOffset?: number; 63 | handlerZIndex?: number; 64 | children?: React.ReactNode | undefined; 65 | } 66 | ``` 67 | 68 | **hooking event listeners** 69 | 70 | ```tsx 71 | handleEditorSizingStart = () => { 72 | // const nearBottom = scrollTop > ... 73 | setShouldStickToBottom(nearBottom); 74 | }; 75 | handleEditorSizingEnd = () => { 76 | if (shouldStickToBottom) { 77 | scrollToBottom(); 78 | } 79 | }; 80 | 81 | 86 | 87 | ; 88 | ``` 89 | 90 | **for umd / <script> usage** 91 | 92 | ```html 93 | 94 | 95 | 96 | 97 | ``` 98 | 99 | ```js 100 | // myapp.js 101 | let React = window.React; 102 | let ReactDOM = window.ReactDOM; 103 | let { DragSizing } = window.ReactDragSizing; 104 | 105 | ReactDOM.render( 106 |
107 | Left bar 108 | 113 |
Main content
114 |
115 |
, 116 | mountNode 117 | ); 118 | ``` 119 | 120 | **for react < 16.8 we need hooks polyfill workaround** 121 | 122 | ```tsx 123 | // todo 124 | ``` 125 | 126 | --- 127 | 128 | This project was bootstrapped with [create-react-library](https://github.com/transitive-bullshit/create-react-library) & [react-ts-demo](https://github.com/fritx/react-ts-demo). 129 | -------------------------------------------------------------------------------- /blog/p/projects/react-drag-sizing/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/react-drag-sizing/demo.gif -------------------------------------------------------------------------------- /blog/p/projects/silent/README.md: -------------------------------------------------------------------------------- 1 | # silent 1.0-legacy 2 | 3 |    4 |      5 | 6 | 7 | 8 | > Be a silent, static blog 9 | 10 | Live Demo:
11 | Also, a branch by @Jayin: [Meizhuo/silentor](https://github.com/Meizhuo/silentor) 12 | 13 | for silent 2.0, check [this](../silent_2.0/) out 14 | 15 | ## Features 16 | 17 | ### Easy: Writing in Markdown 18 | 19 | > Markdown makes contents more **focused** 20 | 21 | Or you can use any other renderer instead 22 | 23 | ### Flexible: Special Page Management 24 | 25 | > With only **1** folder, do it yourself 26 | 27 | Everything is a **page**, and every page is a **file** 28 | 29 | ### Lightweight: You Can't Imagine 30 | 31 | > 1 html, 1 ico, 1 css and 1 js, totally **7K** (excluding jquery & marked) 32 | 33 | ```plain 34 | - blog/ 35 | - p/ (your own things, free to handle) 36 | - posts/ 37 | - my-js-book/ 38 | - index.md 39 | - part-1.md 40 | - part-2.md 41 | - what-a-funny-day.md 42 | - why-i-use-js.md 43 | - sidebar.md 44 | - aboutme.md 45 | - avatar.jpg 46 | - vendor/ (built-in stuffs) 47 | - blog.css 48 | - blog.js 49 | - ... 50 | - favicon.ico 51 | - index.html 52 | ``` 53 | 54 | ### Responsive: All is Well 55 | 56 | > Never mind the screens 57 | 58 | 59 |      60 | 61 | 62 | 63 | 64 | 65 | 66 | ## Silent Fans 67 | 68 | > Thank you! 69 | 70 | - [ZhanZengyu's Blog](https://zhanzengyu.github.io/blog/) 71 | - [Meizhuo's Blog](https://meizhuo.github.io/blog/) 72 | - [Amen's Blog](https://linzx89757.github.io/blog/) 73 | - [Jayin's Blog](https://v1.jayinton.com/blog/) 74 | - [Derek's Blog](https://derekgame2013.github.io/blog/) 75 | - [Huang's Blog](https://huangruichang.github.io) 76 | - [Jason's Blog](https://jacsonlee.github.io/Blog/) 77 | - [Jayden's Blog](https://iamjayden.github.io) 78 | - [Fritx' Blog](https://blog.fritx.me/) 79 | 80 | ## More.. 81 | 82 | > Rather than a framework or library, silent is more like a spirit - a culture. (says Huang) 83 | 84 | - [Silent One Year Old](../../2015/05/silent-one-year-old/) 85 | - ~~[Silent T-Shirt](http://udz.com/silent)~~ 86 | 87 | 88 | -------------------------------------------------------------------------------- /blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-43-18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-43-18.png -------------------------------------------------------------------------------- /blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-48-37.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-48-37.png -------------------------------------------------------------------------------- /blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-50-42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-50-42.png -------------------------------------------------------------------------------- /blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-56-27.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent/pic/Screenshot_from_2014-05-08_01-56-27.png -------------------------------------------------------------------------------- /blog/p/projects/silent/pic/si1ent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent/pic/si1ent.png -------------------------------------------------------------------------------- /blog/p/projects/silent/pic/tshirt-x360.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent/pic/tshirt-x360.png -------------------------------------------------------------------------------- /blog/p/projects/silent_2.0/README.md: -------------------------------------------------------------------------------- 1 | # silent 2.0 2 | 3 |        4 | 5 | 6 | 7 | > Be a silent, static blog 8 | 9 | for silent 1.0, check [this](../silent/) out 10 | 11 | ## 🎉🎉 silent's 10th Anniversary 12 | 13 | SilentPress: a CMS alternative to VitePress and WordPress. 200+LOC written in Go.
14 | https://github.com/fritx/silentpress 15 | 16 | -- for the 10th-anniversary of *silent*. silent and its simplicity was a once a culture, a spirit, and a memory of ____
17 | #silent #10YearsAnniversary #simplicity #opensource 18 | 19 | ## Features 20 | 21 | ### Old-school & Clean 22 | 23 | - [x] no MVVM frameworks (no vue, react, etc) 24 | - [x] no CCS frameworks 25 | - [ ] no jquery 26 | 27 | ### Static & Portable 28 | 29 | - [x] no node_modules (no dependencies, etc) 30 | - [x] no build systems (no gulp, webpack, etc) 31 | - [x] no extra build commands (no npm-run-build or -generate) 32 | - [x] no CI/CD required (github-actions can be optional) 33 | - [x] source code is all it needs to run 34 | - [x] npm-create tooling 35 | 36 | ### Writing, Focus and Visualization 37 | 38 | - [x] markdown 39 | - [x] [mermaid](https://mermaid-js.github.io/mermaid/) diagrams 40 | 41 | ### Extendable & Integration 42 | 43 | - [x] analytics: google, baidu, etc 44 | - [x] comment system: [disqus](https://disqus.com) +[cusdis](https://cusdis.com) +[giscus](https://giscus.app), etc 45 | - [ ] backend permission api 46 | 47 | ### Funny & Fancy & Performance 48 | 49 | - [x] prefer history.pushState api 50 | - [x] progress bar on top 51 | - [x] auto favicon (extracted from title) 52 | - [x] favicon dark mode 53 | - [ ] page-level dark mode 54 | 55 | 56 | 57 | 58 | 59 | ### Security & Stability 60 | 61 | - [x] responsive design 62 | - [x] prefer es5 and guarded with eslint 63 | - [ ] fallback on browser compatibility break 64 | - [ ] IE 6+ support (needs polyfill, etc) 65 | 66 | 67 | 68 | 69 | 70 | ## Usage 71 | 72 | ```sh 73 | # create it 74 | npm create silent 75 | # or 76 | npm i -g silent 77 | silent create 78 | 79 | # e.g. 80 | npm create silent ~/t/my-blog 81 | # >>> 82 | # copying /Users/fritx/.nvm/versions/node/v16.14.0/lib/node_modules/silent/blog 83 | # => /Users/fritx/t/my-blog 84 | # silent-create completed 85 | 86 | # serve it 87 | cd ~/t/my-blog 88 | npx serve . -p 3000 89 | # >>> 90 | # Serving! http://localhost:3000 91 | 92 | # deploy to your github pages? 93 | cd ~/t/my-blog 94 | git init 95 | git remote add origin git@github.com:fritx/silent.git 96 | npx gh-pages -d . 97 | # >>> 98 | # Published. https://fritx.github.io/silent/ 99 | ``` 100 | 101 | ## Browser Compatibility 102 | 103 | Status: no IE 104 | 105 | - [ ] no IE https://caniuse.com/?search=arr%20includes 106 | - [ ] no IE https://caniuse.com/?search=str%20includes 107 | - [ ] no IE https://caniuse.com/?search=builtin%20object%20assign 108 | - [ ] IE10+ https://caniuse.com/?search=console 109 | - [x] IE10+ https://caniuse.com/?search=pushstate 110 | - [ ] IE9+ https://caniuse.com/?search=date.now 111 | - [ ] IE9+ https://caniuse.com/?search=object.keys 112 | - [ ] IE9+ https://caniuse.com/?search=arr%20foreach 113 | - [ ] IE9+ https://caniuse.com/?search=querySelector 114 | - [ ] IE9+ https://caniuse.com/?search=css3%20selectors 115 | - [x] IE8+ https://caniuse.com/?search=scrollintoview 116 | 117 | mermaid: 118 | 119 | - [x] no IE / Safari 15.4+ https://caniuse.com/?search=structuredClone 120 | - [ ] no IE https://caniuse.com/?search=arrow%20function 121 | 122 | auto title favicon: 123 | 124 | - [x] no IE https://caniuse.com/?search=prefers-color-scheme 125 | - [x] IE10+ https://caniuse.com/?search=matchMedia 126 | - [ ] IE9+ https://caniuse.com/?search=canvas 127 | 128 | if using giscus: 129 | 130 | - [ ] no IE https://caniuse.com/?search=ResizeObserver 131 | - [ ] IE8+ https://caniuse.com/?search=postmessage 132 | - [ ] IE8+ https://caniuse.com/?search=localstorage 133 | 134 | ## Silent Fans 135 | 136 | > Thank you! 137 | 138 | - [ZhanZengyu's Blog](https://zhanzengyu.github.io/blog/) 139 | - [Meizhuo's Blog](https://meizhuo.github.io/blog/) 140 | - [Amen's Blog](https://linzx89757.github.io/blog/) 141 | - [Jayin's Blog](https://v1.jayinton.com/blog/) 142 | - [Derek's Blog](https://derekgame2013.github.io/blog/) 143 | - [Huang's Blog](https://huangruichang.github.io) 144 | - [Jason's Blog](https://jacsonlee.github.io/Blog/) 145 | - [Jayden's Blog](https://iamjayden.github.io) 146 | - [Fritx' Blog](https://blog.fritx.me/) 147 | 148 | ## More.. 149 | 150 | > Rather than a framework or library, silent is more like a spirit - a culture. (says Huang) 151 | 152 | - [The 10th Anniversary of *silent*...](https://x.com/fz_ux55200/status/1786274684541321639) 153 | - [SilentPress: CMS Alternative to VitePress and WordPress. 200LOC in Go](https://news.ycombinator.com/item?id=40234012) 154 | - [Silent One Year Old](?2015/05/silent-one-year-old) 155 | - ~~[Silent T-Shirt](http://udz.com/silent)~~ 156 | 157 | 158 | -------------------------------------------------------------------------------- /blog/p/projects/silent_2.0/WX20220927-173925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent_2.0/WX20220927-173925.png -------------------------------------------------------------------------------- /blog/p/projects/silent_2.0/WechatIMG533.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/silent_2.0/WechatIMG533.png -------------------------------------------------------------------------------- /blog/p/projects/timeline.md: -------------------------------------------------------------------------------- 1 | # 📅 Projects timeline 2 | 3 | > All my projects on Github 4 | 5 | ```mermaid 6 | gantt 7 | title 2022 8 | axisFormat %Y-%m 9 | chai-inline-snapshot :2022-09-27 , 2022-09-28 10 | wxacomp-qtext :2022-09-26 , 2022-09-27 11 | qtext-parse :2022-09-26 , 2022-09-27 12 | qqface 2.0 :2022-09-26 , 2022-09-27 13 | silent 2.0 :2022-09-09 , 2022-09-15 14 | bec-admin :2022-08-17 , 2022-09-05 15 | Wuruqitu-docker :2022-08-01 , 2022-08-02 16 | docker-php-apache :2022-08-01 , 2022-08-02 17 | wxapp-digest :2022-07-01 , 2022-08-10 18 | bec-coo :2022-06-24 , 2022-08-12 19 | wxapp-calendar :2022-03-20 , 2022-07-19 20 | wxapp-photos :2022-03-05 , 2022-05-05 21 | docker-chromium-node :2022-02-19 , 2022-02-20 22 | fritxdemo :2022-02-10 , 2022-04-22 23 | digest-v2 :2022-01-28 , 2022-05-28 24 | ``` 25 | 26 | ```mermaid 27 | gantt 28 | title 2018-2022 29 | axisFormat %Y-%m 30 | wxapp-photos-share :2021-03-20 , 2021-04-04 31 | digest :2021-01-10 , 2021-02-21 32 | react-drag-sizing 2.0 :2020-04-05 , 2020-04-06 33 | coldemo :2020-03-22 , 2020-06-18 34 | react-editor 2.0 :2020-02-16 , 2020-03-22 35 | PureProxy :2020-01-27 , 2020-05-17 36 | Nofred :2019-12-01 , 2019-12-14 37 | fritxbash :2019-08-25 , 2019-12-15 38 | fritxservice :2019-06-23 , 2019-08-20 39 | fritxsite :2019-06-23 , 2019-08-20 40 | fritxweapp2 :2019-03-23 , 2019-08-21 41 | wxproxy :2019-02-28 , 2019-04-06 42 | digest-service :2019-02-16 , 2019-07-12 43 | awesome-yuan :2019-01-28 , 2019-01-29 44 | add-a :2018-09-15 , 2018-09-16 45 | SorryPress :2018-04-23 , 2018-05-03 46 | sqlcipher-electron-demo :2018-04-19 , 2018-04-20 47 | fritxweapp1 :2018-01-21 , 2019-03-24 48 | szw-server :2018-01-18 , 2019-02-23 49 | ``` 50 | 51 | ```mermaid 52 | gantt 53 | title 2015-2018 54 | axisFormat %Y-%m 55 | gh-wxpay :2017-10-24 , 2017-10-29 56 | vue-the-aviator :2017-09-26 , 2017-09-28 57 | vue-server-demo :2017-09-23 , 2017-09-25 58 | koa-captcha-2 :2017-08-01 , 2017-09-12 59 | mongo-model-2 :2017-06-04 , 2018-06-09 60 | schema-validator2 :2017-05-30 , 2017-07-05 61 | cms-server :2017-04-13 , 2017-09-01 62 | cms-admin :2017-04-08 , 2017-09-01 63 | wxbot 2.0 :2017-03-14 , 2017-10-03 64 | react-drag-sizing :2017-03-05 , 2017-03-07 65 | share.wx :2017-02-05 , 2017-06-25 66 | vue-at :2016-12-17 , 2018-06-10 67 | react-at :2016-12-14 , 2016-12-17 68 | react-native-auto-scroll :2016-10-02 , 2016-10-04 69 | cross-sqlcipher :2016-09-30 , 2016-10-20 70 | mp.wx :2016-08-06 , 2017-06-18 71 | FEbps :2016-06-14 , 2016-07-16 72 | evm :2016-06-07 , 2016-06-09 73 | vue-mpwx :2016-05-29 , 2016-06-06 74 | vue-threejs :2016-05-22 , 2017-10-18 75 | awesome-threejs :2016-05-21 , 2016-05-23 76 | jayin :2016-05-15 , 2016-07-16 77 | git-green-someone-else :2016-05-08 , 2016-05-10 78 | cross-unzip :2016-04-27 , 2017-03-19 79 | react-threejs :2016-04-04 , 2016-06-11 80 | nw-remote :2016-03-29 , 2016-04-03 81 | nw-auto :2016-03-17 , 2016-04-27 82 | awesome-wechat :2016-03-08 , 2016-09-20 83 | nw-shot :2016-02-14 , 2016-03-06 84 | react-editor :2016-01-03 , 2016-12-14 85 | xq :2015-11-21 , 2016-02-09 86 | paste :2015-11-06 , 2015-11-07 87 | wxbot :2015-09-20 , 2016-11-19 88 | ``` 89 | 90 | ```mermaid 91 | gantt 92 | title 2014-2015 93 | axisFormat %Y-%m 94 | jsonedit :2015-09-03 , 2015-09-04 95 | PUM :2015-08-24 , 2015-09-09 96 | threejs-galaxy :2015-08-04 , 2015-08-13 97 | prt :2015-07-26 , 2015-07-27 98 | dwn :2015-07-21 , 2015-07-23 99 | exc :2015-07-17 , 2015-07-19 100 | bib idea 2.0 :2015-07-01 , 2015-08-21 101 | awesome-nwjs :2015-06-23 , 2015-08-10 102 | mda :2015-05-15 , 2015-05-16 103 | cookiedog :2015-05-01 , 2015-05-02 104 | markppt :2015-04-07 , 2015-09-01 105 | wxchangba :2015-03-07 , 2015-06-07 106 | qqlog :2015-01-26 , 2015-09-15 107 | wqq :2015-01-26 , 2015-09-15 108 | channel :2015-01-15 , 2015-05-03 109 | wxtopic :2015-01-15 , 2015-02-03 110 | fs-auth :2015-01-04 , 2015-01-06 111 | n0gx :2015-01-03 , 2015-02-11 112 | quick-pay :2014-12-19 , 2014-12-20 113 | copytouch :2014-12-15 , 2015-01-06 114 | quick-login :2014-12-14 , 2014-12-15 115 | prj :2014-12-10 , 2014-12-17 116 | todoo :2014-11-29 , 2014-11-30 117 | expresso-demo :2014-11-22 , 2014-11-23 118 | onedoc :2014-11-19 , 2014-11-21 119 | virtual-fs :2014-11-16 , 2014-11-17 120 | task :2014-10-11 , 2014-10-12 121 | passwordless-mailer :2014-10-01 , 2014-10-02 122 | repo-template :2014-09-27 , 2014-10-31 123 | easy-emitter :2014-09-27 , 2014-10-24 124 | ``` 125 | 126 | ```mermaid 127 | gantt 128 | title 2012-2014 129 | axisFormat %Y-%m 130 | bib idea :2014-09-13 , 2014-09-14 131 | quiet :2014-09-13 , 2014-09-15 132 | gulp-mail :2014-09-11 , 2014-09-12 133 | gulp-edit :2014-09-11 , 2014-09-12 134 | aniamte-js :2014-09-06 , 2014-09-11 135 | translate-gg-cn :2014-08-16 , 2014-08-18 136 | emshop :2014-07-10 , 2014-08-26 137 | gui-cli :2014-06-11 , 2014-06-17 138 | a-sync :2014-06-07 , 2014-06-09 139 | gulp-eol :2014-05-22 , 2014-09-06 140 | silent :2014-05-08 , 2015-07-05 141 | eager :2014-05-04 , 2014-05-06 142 | great :2014-05-02 , 2014-05-08 143 | wyu-sing :2014-04-23 , 2014-11-13 144 | bounty-hunter :2014-04-09 , 2014-06-11 145 | mshop :2014-03-22 , 2014-06-13 146 | freeblog :2013-12-27 , 2014-01-09 147 | translat :2013-12-18 , 2013-12-20 148 | siyuan :2013-12-10 , 2014-03-28 149 | vbro :2013-12-06 , 2013-12-07 150 | wxpub :2013-11-28 , 2013-11-30 151 | voice1min :2013-10-14 , 2013-10-21 152 | wxbase-app :2013-10-04 , 2013-10-11 153 | yjjapp :2013-09-26 , 2013-12-01 154 | worldmin :2013-09-15 , 2013-09-16 155 | wallwx :2013-09-14 , 2013-09-15 156 | jmsis :2013-09-11 , 2015-06-29 157 | walley :2013-09-10 , 2013-09-14 158 | xstu :2013-09-04 , 2013-09-09 159 | ontodo :2013-08-29 , 2013-08-30 160 | cucudb :2013-07-31 , 2013-08-28 161 | remindme :2013-07-07 , 2013-07-08 162 | freegolf :2013-06-19 , 2013-06-21 163 | spacewar :2013-05-20 , 2013-05-21 164 | Wuruqitu :2013-02-15 , 2013-02-17 165 | xydd :2012-09-26 , 2012-12-01 166 | ``` 167 | -------------------------------------------------------------------------------- /blog/p/projects/vue-at/README.md: -------------------------------------------------------------------------------- 1 | # 👨‍👩‍👧‍👦 vue-at  [![](https://img.shields.io/github/stars/fritx/vue-at?style=social)](https://github.com/fritx/vue-at) 2 | 3 |         Join the chat at https://gitter.im/fritx/vue-at 4 | 5 |    6 | 7 | - [x] Chrome / Firefox / Edge / IE9~IE11 8 | - [x] Plain-text based, no jQuery, no extra nodes 9 | - [x] Content-Editable / Textarea 10 | - [x] Avatars, custom templates 11 | - [x] Vite / Vue3 / Vue2 / Vue1 12 | - [x] Quasar / Vuetify / Element UI / Element Plus 13 | - [x] Vue-CLI build migration 14 | - [ ] Vite build migration 15 | - [x] CommonJS / UMD Support 16 | 17 | Playground: https://we-demo.github.io/vue-at-vite-app/
18 | Vue2 Docs: https://github.com/fritx/vue-at/tree/vue2#readme
19 | Vue3 Docs: See below
20 | See also: [react-at](https://github.com/fritx/react-at) 21 | 22 | **If you're using Vue2, read [branch vue2](https://github.com/fritx/vue-at/tree/vue2#readme) instead.** 23 | 24 | ```plain 25 | npm i vue-at@next # for Vue3 (branch vue3) 26 | npm i vue-at@2.x # for Vue2 (branch vue2) 27 | npm i vue-at@1.x # for Vue1 (branch vue1-legacy) 28 | npm i vue1-at # for Vue1 (branch vue1-new) 29 | ``` 30 | 31 | ```vue 32 | 40 | 41 | 54 | 55 | 59 | ``` 60 | 61 | ## UMD Also Supported 62 | 63 | ```html 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
75 | 76 |
77 |
78 | 79 | 80 | 81 |
82 | 88 | ``` 89 | 90 | ## Using V-Model (Recommended) 91 | 92 | With Content-Editable, use ``
93 | With Textarea, you can use either `` or ` 101 | 102 | 103 | 104 | 105 | ``` 106 | 107 | ## Custom Templates 108 | 109 | ### Custom List 110 | 111 | ```vue 112 | 121 | 122 | 132 | 133 | 138 | ``` 139 | 140 | #### Custom List with Vue 1.x 141 | 142 | There is no "scoped slot" feature in Vue 1.
143 | Use a "normal slot" with `data-` attribute instead. 144 | 145 | ```vue 146 | 147 | 151 | ``` 152 | 153 | ### Custom Tags 154 | 155 | This gives you the option of changing the style of inserted tagged items. It is only supported for ContentEditable version, not Textarea. 156 | 157 | ```vue 158 | 159 | {{ s.current.name }} 160 | 161 | 162 | 163 | 164 | 167 | ``` 168 | 169 | ## Used with 3rd-party libraries 170 | 171 | ### Vuetify v-textarea 172 | 173 | ```vue 174 | 175 | 176 | 177 | 178 | ``` 179 | 180 | ### Element UI / Element-Plus el-input 181 | 182 | ```vue 183 | 184 | 185 | 186 | 187 | ``` 188 | -------------------------------------------------------------------------------- /blog/p/projects/vue-at/WechatIMG1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/vue-at/WechatIMG1.jpeg -------------------------------------------------------------------------------- /blog/p/projects/vue-at/WechatIMG2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fritx/silent/baa316784116a14c67ea5e3dc5fb1b4288af30a6/blog/p/projects/vue-at/WechatIMG2.jpeg -------------------------------------------------------------------------------- /blog/p/projects/website-badge.svg: -------------------------------------------------------------------------------- 1 | website: upwebsiteup -------------------------------------------------------------------------------- /blog/p/reports.md: -------------------------------------------------------------------------------- 1 | # 🔐 Reports 2 | 3 | ```mermaid 4 | gantt 5 | title A Gantt Diagram 6 | axisFormat %Y-%m 7 | section Section 8 | A task :a1, 2019-01-01, 30d 9 | Another task :after a1 , 20d 10 | section Another 11 | Task in sec :2019-01-12 , 12d 12 | another task : 24d 13 | ``` 14 | 15 | ```mermaid 16 | gantt 17 | title 项目开发流程 18 | section 项目确定 19 | 需求分析 :a1, 2019-06-22, 3d 20 | 可行性报告 :after a1, 5d 21 | 概念验证 : 5d 22 | section 项目实施 23 | 概要设计 :2019-07-05 , 5d 24 | 详细设计 :2019-07-08, 10d 25 | 编码 :2019-07-15, 10d 26 | 测试 :2019-07-22, 5d 27 | section 发布验收 28 | 发布: 2d 29 | 验收: 3d 30 | ``` 31 | -------------------------------------------------------------------------------- /blog/p/sidebar.md: -------------------------------------------------------------------------------- 1 | # [My Blog](..) 2 | 3 | > Life is short, I use JS 4 | 5 | - [🔐 Reports](reports/) 6 | - [🌈 Posts](posts.md) 7 | - [🎯 Projects](projects/) 8 | - [😅 About Me](aboutme.md) 9 | -------------------------------------------------------------------------------- /blog/vendor/blog.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | line-height: 1.5; 5 | font-size: 106%; 6 | /*font-family: "Microsoft YaHei", sans-serif;*/ 7 | /*font-family: "Helvetica neue",Helvetica,Tahoma,"lantinghei sc","Microsoft Yahei", sans-serif;*/ 8 | font-family: "Helvetica neue", "Microsoft Yahei", sans-serif; 9 | word-break: break-word; 10 | /* word-break: break-all; */ 11 | background-color: #fff; 12 | } 13 | 14 | hr { 15 | border: none; 16 | border-bottom: dashed 2px #D3DCE6; /* element-ui gray */ 17 | } 18 | 19 | img { 20 | border: 0; 21 | max-width: 100%; 22 | /* height: auto; */ 23 | } 24 | ul, ol { 25 | padding-left: 30px; 26 | } 27 | 28 | code, kbd, pre, samp { /* normalize.css */ 29 | font-family: monospace, monospace; 30 | font-size: 1em; 31 | } 32 | 33 | /* 隐藏局部滚动条 样式兼容问题 */ 34 | pre code::-webkit-scrollbar, table::-webkit-scrollbar{display:none;} 35 | 36 | pre { 37 | word-break: break-all; 38 | } 39 | code { 40 | /* .hljs zenburn */ 41 | background: #3f3f3f; 42 | color: #dcdcdc; 43 | font-size: 80%; 44 | -webkit-border-radius: 6px; /* 同scroller圆角 */ 45 | border-radius: 6px; 46 | } 47 | pre code, pre code.hljs { 48 | display: block; 49 | overflow-x: auto; 50 | padding: 0.6em 1em; 51 | } 52 | 53 | /* learnt from github */ 54 | table { 55 | font-size: 80%; 56 | width: 100%; 57 | overflow: auto; 58 | word-break: normal; 59 | display: block; 60 | margin: 15px 0; 61 | border-collapse: collapse; 62 | border-spacing: 0; 63 | } 64 | table th, table td { 65 | border: 1px solid #ddd; 66 | padding: 6px 13px; 67 | min-width: 4em; 68 | } 69 | table tr { 70 | border-top: 1px solid #ccc; 71 | background-color: #fff; 72 | } 73 | table tr:nth-child(2n) { 74 | background-color: #f8f8f8; 75 | } 76 | blockquote { 77 | margin: 15px 0; 78 | border-left: 4px solid #DDD; 79 | padding: 0 15px; 80 | color: #777; 81 | } 82 | a { 83 | color: #4078c0; 84 | } 85 | 86 | .sidebar { 87 | color: #fff; 88 | } 89 | .sidebar-inner { 90 | padding: 2% 5%; 91 | } 92 | .sidebar ul, .sidebar ol { 93 | padding-left: 0; 94 | } 95 | .sidebar li { 96 | display: inline-block; 97 | margin-right: .3em; 98 | } 99 | .sidebar a { 100 | color: #fff; 101 | } 102 | .sidebar h1 a { 103 | text-decoration: none; 104 | } 105 | .sidebar blockquote { 106 | color: #bbb; 107 | } 108 | 109 | .main-inner { 110 | padding: 2% 5% 6%; 111 | } 112 | #comment-system { 113 | padding-top: 3%; 114 | } 115 | #comment-system:empty { 116 | padding-top: 0; 117 | } 118 | .main-page img { 119 | /*-webkit-box-shadow: 0 0 6px rgba(0,0,0, .6); 120 | -moz-box-shadow: 0 0 6px rgba(0,0,0, .6); 121 | -ms-box-shadow: 0 0 6px rgba(0,0,0, .6); 122 | -o-box-shadow: 0 0 6px rgba(0,0,0, .6); 123 | box-shadow: 0 0 6px rgba(0,0,0, .6);*/ 124 | /* fix transparent image background in darkmode */ 125 | background-color: rgba(255, 255, 255, .2); 126 | } 127 | 128 | .img-holder { 129 | position: absolute; 130 | top: -9999px; 131 | left: -9999px; 132 | } 133 | 134 | .fork-me { 135 | position: absolute; 136 | right: 0; 137 | top: 0; 138 | z-index: 9999; 139 | } 140 | 141 | /* 实现trello的 超链接效果 自动识别github issues */ 142 | .known-service-link { 143 | font-size: 90%; 144 | color: #444; 145 | background: #D6DADC; 146 | border-radius: 3px; 147 | /* avoid linebreak between icon and text */ 148 | word-break: break-all; 149 | } 150 | .known-service-icon { 151 | width: 14px; 152 | height: 14px; 153 | margin: -2px 3px 0 0; 154 | vertical-align: middle; 155 | } 156 | 157 | /* 暂时感觉这类标签应该inline-block展示 */ 158 | code, 159 | .known-service-link { 160 | display: inline-block; 161 | margin: 2px; 162 | padding: 0 4px; 163 | } 164 | 165 | @media (min-width: 640px) { 166 | ul, ol { 167 | padding-left: 40px; 168 | } 169 | table { 170 | font-size: 100%; 171 | } 172 | 173 | .sidebar-inner { 174 | padding: 2% 10%; 175 | } 176 | 177 | .main-inner { 178 | padding-left: 10%; 179 | padding-right: 10%; 180 | } 181 | 182 | .fork-me { 183 | position: fixed; 184 | } 185 | } 186 | 187 | @media (min-width: 990px) { 188 | .sidebar { 189 | position: fixed; 190 | top: 0; 191 | bottom: 0; 192 | left: 0; 193 | width: 25%; 194 | } 195 | .sidebar ul, .sidebar ol { 196 | padding-left: 30px; 197 | } 198 | .sidebar li { 199 | display: list-item; 200 | margin-right: 0; 201 | } 202 | .sidebar-inner { 203 | padding: 15%; 204 | } 205 | 206 | .main { 207 | margin-left: 25%; 208 | width: 75%; 209 | } 210 | } 211 | 212 | /* avoid losing height while swithcing contents */ 213 | .contents-preparing { 214 | visibility: hidden; 215 | } 216 | 217 | /* pace minimal */ 218 | /* https://codebyzach.github.io/pace/ */ 219 | .pace { 220 | -webkit-pointer-events: none; 221 | pointer-events: none; 222 | -webkit-user-select: none; 223 | -moz-user-select: none; 224 | user-select: none; 225 | } 226 | .pace-inactive { 227 | display: none; 228 | } 229 | .pace .pace-progress { 230 | background: #29d; 231 | position: fixed; 232 | z-index: 2000; 233 | top: 0; 234 | right: 100%; 235 | width: 100%; 236 | height: 2px; 237 | } 238 | 239 | /* mermaid lazyload */ 240 | .mermaid { 241 | visibility: hidden; 242 | } 243 | .mermaid[data-processed="true"] { 244 | visibility: visible; 245 | } 246 | -------------------------------------------------------------------------------- /blog/vendor/blog.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by fritx on 5/7/14. 3 | */ 4 | 5 | ;(function () { 6 | 'use strict' 7 | 8 | var pageExt, pageBase 9 | var sidebarPage, defaultPage 10 | var mainPage, mainTitle 11 | var mainPageId, mainSearch 12 | var useCache = true 13 | 14 | function loadSidebar() { 15 | load('#sidebar-page', sidebarPage) 16 | } 17 | 18 | function loadMain(search, callback, isPopState) { 19 | mainSearch = search 20 | // fix: /?2022%2F09%2Fblog-setup-via-github-fork 21 | var seg = decodeURIComponent(search).slice(1).replace(/[&#].*$/g, '') 22 | // fucking wechat again 23 | // like /?graduation-thanks= 24 | // or /?graduation-thanks=/ (SublimeServer) 25 | seg = seg.replace(/=[/\\]*$/, '') 26 | // fucking wechat pending 27 | // like /?from=singlemessage&isappinstalled=0 28 | if (/=/.test(seg)) seg = null 29 | mainPage = resolve(seg || defaultPage) 30 | load('#main-page', mainPage, true, callback, isPopState) 31 | } 32 | 33 | function load(sel, stack, isMain, callback, isPopState) { 34 | if (typeof stack === 'string') { 35 | if (/\/$/.test(stack)) { 36 | stack = [stack + 'index', stack + 'README', stack.replace(/\/$/, '')] 37 | } else { 38 | stack = [stack, stack + '/index', stack + '/README'] 39 | } 40 | } 41 | 42 | var pageId = stack.shift() 43 | isMain = isMain || false 44 | if (isMain) mainPageId = pageId 45 | 46 | var url = pageBase + pageId + pageExt 47 | $.ajax({ 48 | url: url, 49 | cache: useCache, 50 | error: function (err) { 51 | if (isMain && pageId !== mainPageId) return 52 | 53 | if (stack.length) { 54 | return load(sel, stack, isMain, callback, isPopState) 55 | } 56 | if (isMain) onNotFound(err) 57 | }, 58 | success: function (data) { 59 | if (isMain && pageId !== mainPageId) return 60 | 61 | render(data, function (err, html) { 62 | if (isMain && pageId !== mainPageId) return 63 | 64 | if (err) { 65 | return console.error('render err', err) 66 | } 67 | var $el = $(sel) 68 | $el.addClass('contents-preparing').html(html) 69 | postProcess($el, url) 70 | 71 | $el.removeClass('contents-preparing').attr('data-loaded', '') 72 | if (isMain) onMainRendered(isPopState) 73 | if (callback) callback() 74 | }) 75 | } 76 | }) 77 | } 78 | 79 | function postProcess($el, url) { 80 | var dir = url.replace(/[^\\/]*$/, '') 81 | 82 | $el.find('[src]').each(function () { 83 | var $el = $(this) 84 | $el.attr('src', function (x, old) { 85 | if ($el.attr('data-noop') != null) { 86 | return old 87 | } 88 | if (isAbsolute(old)) { 89 | return old 90 | } 91 | return resolve(dir + old) 92 | }) 93 | }) 94 | 95 | $el.find('[href]').each(function () { 96 | var $el = $(this) 97 | $el.attr('href', function (x, old) { 98 | var isJs = /^javascript:/i.test(old) 99 | if (isJs) return old 100 | if (isAbsolute(old)) { 101 | $el.attr('target', '_blank') 102 | return old 103 | } 104 | if (/^\?/.test(old)) { 105 | // supports in-site ?-search 106 | return old 107 | } 108 | var prefixed = resolve(dir + old) 109 | var hashRegex = /#.*/ 110 | var hash = (function (match) { 111 | return match && match[0] || '' 112 | })(old.match(hashRegex)) 113 | var dehashed = prefixed.replace(hashRegex, '') 114 | 115 | var extRegex = new RegExp(slashes(pageExt) + '$') 116 | if (extRegex.test(dehashed) || /\/$/.test(dehashed)) { 117 | return ( 118 | '?' + 119 | dehashed 120 | .replace(new RegExp('^' + slashes(pageBase)), '') 121 | .replace(extRegex, '') + 122 | hash 123 | ) 124 | } 125 | return prefixed 126 | }) 127 | }) 128 | 129 | $el.find('p').each(function () { 130 | var $el = $(this) 131 | $el.html(function (x, old) { 132 | return old.replace(/\n+/g, '') 133 | }) 134 | }) 135 | 136 | $el.find('pre code').each(function (i, el) { 137 | hljs.highlightBlock(el) 138 | }) 139 | } 140 | 141 | var isMermaidLoaded = false 142 | 143 | function onMainRendered(isPopState) { 144 | mainTitle = $('#main-page').find('h1, h2, h3, h4, h5, h6').first().text().trim() 145 | var navTitle = autoTitleFavicon(mainTitle) 146 | document.title = navTitle 147 | 148 | // supports mermaid diagrams 149 | if ($('#main-page').find('.mermaid').length) { 150 | if (isMermaidLoaded) { 151 | mermaid.init() 152 | } else { 153 | // var src = 'vendor/mermaid-11.3.0.min.js' // 2.55 MB 154 | // var src = 'vendor/mermaid-11.2.1.min.js' // 2.51 MB 155 | // var src = 'vendor/mermaid-11.0.2.min.js' // 2.33 MB 156 | // var src = 'vendor/mermaid-10.9.3.min.js' // 3.34 MB 157 | // 以上 iPX 不ok - Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.2 Mobile/15E148 Safari/604.1 158 | // var src = 'vendor/mermaid-9.4.3.min.js' // 2.78 MB 159 | var src = 'vendor/mermaid-9.1.7.min.js' // 1.08 MB 160 | loadScript(src, function() { 161 | isMermaidLoaded = true 162 | mermaid.mermaidAPI.initialize({ startOnLoad: false }) 163 | // https://mermaid-js.github.io/mermaid/#/usage?id=calling-mermaidinit 164 | mermaid.parseError = function (err, hash) { 165 | console.error('mermaid.parseError', err, hash) 166 | } 167 | mermaid.init() 168 | }) 169 | } 170 | } 171 | 172 | if (!isPopState) { 173 | setTimeout(scrollToAnchorIfExists, 500) 174 | } 175 | var comments = window.silentComments 176 | if (comments) comments() 177 | shares() 178 | } 179 | function loadScript(src, onload) { 180 | var s = document.createElement('script') 181 | s.src = src 182 | s.onload = onload 183 | s.onerror = function(event) { 184 | console.error('loadScript s.onerror', event, src) 185 | _queueToReport('loadScript_error', { 186 | title: event.message, 187 | error: event.error, 188 | filename: event.filename, 189 | lineno: event.lineno, 190 | colno: event.colno 191 | }) 192 | } 193 | document.body.appendChild(s) 194 | } 195 | 196 | function onNotFound() { 197 | if ($('#main-page').attr('data-loaded') != null) { 198 | // noop 199 | } else if (location.search) { 200 | location.href = '.' 201 | } 202 | } 203 | 204 | function scrollToAnchorIfExists() { 205 | // location.hash is either empty or leading with `#` 206 | // so the selector here is safe 207 | var $anchor = $(location.hash) 208 | if ($anchor.length) scrollIntoView($anchor[0]) 209 | } 210 | 211 | // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded 212 | function scrollIntoView(el, scrollParent) { 213 | if (el.scrollIntoView) { 214 | el.scrollIntoView(true) // alignToTop=true 215 | } else { 216 | scrollParent = scrollParent || el.parentElement 217 | var diff = el.offsetTop - scrollParent.scrollTop 218 | if (diff < 0 || diff > scrollParent.offsetHeight - el.offsetHeight) { 219 | scrollParent.scrollTop = el.offsetTop 220 | } 221 | } 222 | } 223 | 224 | function slashes(str) { 225 | return str.replace(/([.?*+^$!:[\]\\(){}|-])/g, '\\$1') 226 | } 227 | 228 | // How to test if a URL string is absolute or relative? 229 | // https://stackoverflow.com/questions/10687099/how-to-test-if-a-url-string-is-absolute-or-relative 230 | // https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax 231 | function isAbsolute(url) { 232 | return /^(ftp:|https?:)?\/\//i.test(url) || /^(mailto|tel):/i.test(url) 233 | } 234 | 235 | function resolve(path) { 236 | // path = path.replace(/\/+$/, '') // ignore trailing slash 237 | var segs = path.split('/') 238 | var buf = [] 239 | for (var i = 0; i < segs.length; i++) { 240 | var seg = segs[i] 241 | if (seg === '.') continue 242 | var last = buf[buf.length - 1] 243 | if (seg === '..' && last && last !== '..') { 244 | buf.pop() 245 | continue 246 | } 247 | buf.push(seg) 248 | } 249 | return buf.join('/') || '.' 250 | } 251 | 252 | function htmlEntityEncode(str) { 253 | var dom = document.createElement('div') 254 | dom.textContent = str 255 | return dom.innerHTML 256 | } 257 | 258 | // How to detect if the OS is in dark mode in browsers? 259 | // https://stackoverflow.com/questions/50840168/how-to-detect-if-the-os-is-in-dark-mode-in-browsers 260 | // https://caniuse.com/?search=prefers-color-scheme 261 | // https://caniuse.com/?search=matchMedia 262 | var isDarkMode = false 263 | var darkModeChangeHandlers = [] 264 | if (typeof window.matchMedia === 'function') { 265 | if (window.matchMedia('(prefers-color-scheme: dark)').matches) { 266 | isDarkMode = true 267 | } 268 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) { 269 | isDarkMode = !!e.matches 270 | darkModeChangeHandlers.forEach(function (handler) { 271 | handler() 272 | }) 273 | }) 274 | } 275 | 276 | // TODO library extraction: title-favicon & text-favicon & emoji-detect 277 | // How to detect emoji using javascript 278 | // https://stackoverflow.com/questions/18862256/how-to-detect-emoji-using-javascript 279 | // +modification title-favicon bugfix: recognize emoji `✋🏻` `💁‍♀️` `👨‍👩‍👧‍👦` `🏳️‍🌈` 280 | var emojiCellRegex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|\ud83c[\ude32-\ude3a]|\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])+/ 281 | var emojiRegex = new RegExp(emojiCellRegex.toString().replace(/^\/(.+)\/$/, '(?:[\\u200d\\ufe0f]*$1)+[\\ufe0f]*')) 282 | var emojiPrefixRegex = new RegExp(emojiRegex.toString().replace(/^\/(.+)\/$/, '^$1')) 283 | var anyPrefixRegex = new RegExp(emojiPrefixRegex.toString().replace(/^\/\^(.+)\/$/, '^(?:$1|.)')) 284 | 285 | // Use emoji as favicon in websites 286 | // https://stackoverflow.com/questions/59431371/use-emoji-as-favicon-in-websites 287 | var lastFavicon = '' 288 | function setFavicon(s) { 289 | try { 290 | var canvas = document.createElement('canvas') 291 | canvas.height = 32 292 | canvas.width = 32 293 | var ctx = canvas.getContext('2d') 294 | var isEmoji = emojiPrefixRegex.test(s) 295 | ctx.font = isEmoji ? '28px serif' : '32px serif' 296 | ctx.fillStyle = isDarkMode ? 'orange' : '#336699' // for text color 297 | ctx.textAlign = 'center' 298 | ctx.fillText(s, 16, 24) 299 | var dataUrl = canvas.toDataURL() 300 | 301 | var parent = document.querySelector('head') || document.documentElement 302 | var rels = ['icon'] 303 | rels.forEach(function (key) { 304 | var link = document.querySelector('link[rel=' + key + ']') 305 | if (link) { 306 | link.setAttribute('href', dataUrl) 307 | } else { 308 | link = document.createElement('link') 309 | link.setAttribute('rel', key) 310 | link.setAttribute('href', dataUrl) 311 | parent.appendChild(link) 312 | } 313 | }) 314 | 315 | lastFavicon = s 316 | return true // success flag 317 | } catch (err) { 318 | // ignore 319 | // keep it save in case of browser compatibility issues 320 | console.error('setFavicon', err) 321 | } 322 | } 323 | darkModeChangeHandlers.push(function () { 324 | if (lastFavicon) setFavicon(lastFavicon) 325 | }) 326 | 327 | function detectShouldApplyFavicon() { 328 | var ua = navigator.userAgent 329 | var isMobile = /Mobile[/ ]|Android|iPad/.test(ua) // confidence: high 330 | var isHuaweiBr = /HuaweiBrowser/.test(ua) // confidence: high 331 | var isWechat = /MicroMessenger|Wechat|Weixin/.test(ua) // confidence: high 332 | var isQQ = /M?QQBrowser/.test(ua) // confidence: high 333 | var isSafari = /Version\/[\d.]+\s+Safari/.test(ua) // confidence: low 334 | return !isWechat && !isSafari && (isMobile ? isHuaweiBr || isQQ : true) 335 | } 336 | var shouldApplyFavicon = detectShouldApplyFavicon() 337 | 338 | function autoTitleFavicon(mainTitle, emojiOnly) { 339 | var regex = emojiOnly ? emojiPrefixRegex : anyPrefixRegex 340 | var navTitle = mainTitle 341 | if (!shouldApplyFavicon) return navTitle 342 | 343 | var matched = mainTitle.match(regex) 344 | if (matched) { 345 | var prefix = matched[0] 346 | var success = setFavicon(prefix) 347 | if (success && emojiPrefixRegex.test(mainTitle)) { 348 | // navTitle = mainTitle.replace(regex, '').trim() // replace only if emoji 349 | navTitle = mainTitle.replace(prefix, '').trim() // replace only if emoji 350 | } 351 | } 352 | return navTitle 353 | } 354 | 355 | // opt.1 disqus 356 | // https://disqus.com/admin/install/platforms/universalcode/ 357 | var disqusInitiated = false 358 | window.silentDisqus = function (shortName, title, id) { 359 | /* global DISQUS, disqus_shortname */ 360 | window.disqus_shortname = shortName 361 | window.disqus_title = title 362 | window.disqus_identifier = id 363 | window.disqus_url = location.href 364 | // Using Disqus on AJAX sites 365 | // https://help.disqus.com/en/articles/1717163-using-disqus-on-ajax-sites 366 | if (disqusInitiated) { 367 | if (window.DISQUS) DISQUS.reset({ reload: true }) 368 | return 369 | } 370 | disqusInitiated = true 371 | $('
').attr({ id: 'disqus_thread' }).appendTo('#comment-system') 372 | // adding setTimeout to prevent favicon from keeping loading instead of showing 373 | // (disqus.com gets blocked when it's in GFW) 374 | setTimeout(function () { 375 | $('",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}}); -------------------------------------------------------------------------------- /blog/vendor/marked-0.5.0.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * marked - a markdown parser 3 | * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed) 4 | * https://github.com/markedjs/marked 5 | */ 6 | !function(e){"use strict";var k={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:g,hr:/^ {0,3}((?:- *){3,}|(?:_ *){3,}|(?:\* *){3,})(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *(?:#+ *)?(?:\n+|$)/,nptable:g,blockquote:/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:"^ {0,3}(?:<(script|pre|style)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?\\?>\\n*|\\n*|\\n*|)[\\s\\S]*?(?:\\n{2,}|$)|<(?!script|pre|style)([a-z][\\w-]*)(?:attribute)*? */?>(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$)|(?=\\h*\\n)[\\s\\S]*?(?:\\n{2,}|$))",def:/^ {0,3}\[(label)\]: *\n? *]+)>?(?:(?: +\n? *| *\n *)(title))? *(?:\n+|$)/,table:g,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,paragraph:/^([^\n]+(?:\n(?!hr|heading|lheading| {0,3}>|<\/?(?:tag)(?: +|\n|\/?>)|<(?:script|pre|style|!--))[^\n]+)*)/,text:/^[^\n]+/};function a(e){this.tokens=[],this.tokens.links=Object.create(null),this.options=e||d.defaults,this.rules=k.normal,this.options.pedantic?this.rules=k.pedantic:this.options.gfm&&(this.options.tables?this.rules=k.tables:this.rules=k.gfm)}k._label=/(?!\s*\])(?:\\[\[\]]|[^\[\]])+/,k._title=/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/,k.def=t(k.def).replace("label",k._label).replace("title",k._title).getRegex(),k.bullet=/(?:[*+-]|\d+\.)/,k.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,k.item=t(k.item,"gm").replace(/bull/g,k.bullet).getRegex(),k.list=t(k.list).replace(/bull/g,k.bullet).replace("hr","\\n+(?=\\1?(?:(?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$))").replace("def","\\n+(?="+k.def.source+")").getRegex(),k._tag="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|section|source|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",k._comment=//,k.html=t(k.html,"i").replace("comment",k._comment).replace("tag",k._tag).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),k.paragraph=t(k.paragraph).replace("hr",k.hr).replace("heading",k.heading).replace("lheading",k.lheading).replace("tag",k._tag).getRegex(),k.blockquote=t(k.blockquote).replace("paragraph",k.paragraph).getRegex(),k.normal=f({},k),k.gfm=f({},k.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\n? *\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),k.gfm.paragraph=t(k.paragraph).replace("(?!","(?!"+k.gfm.fences.source.replace("\\1","\\2")+"|"+k.list.source.replace("\\1","\\3")+"|").getRegex(),k.tables=f({},k.gfm,{nptable:/^ *([^|\n ].*\|.*)\n *([-:]+ *\|[-| :]*)(?:\n((?:.*[^>\n ].*(?:\n|$))*)\n*|$)/,table:/^ *\|(.+)\n *\|?( *[-:]+[-| :]*)(?:\n((?: *[^>\n ].*(?:\n|$))*)\n*|$)/}),k.pedantic=f({},k.normal,{html:t("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",k._comment).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/}),a.rules=k,a.lex=function(e,t){return new a(t).lex(e)},a.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},a.prototype.token=function(e,t){var n,r,s,i,l,o,a,h,p,u,c,g,f,d,b,m;for(e=e.replace(/^ +$/gm,"");e;)if((s=this.rules.newline.exec(e))&&(e=e.substring(s[0].length),1 ?/gm,""),this.token(s,t),this.tokens.push({type:"blockquote_end"});else if(s=this.rules.list.exec(e)){for(e=e.substring(s[0].length),a={type:"list_start",ordered:d=1<(i=s[2]).length,start:d?+i:"",loose:!1},this.tokens.push(a),n=!(h=[]),f=(s=s[0].match(this.rules.item)).length,c=0;c?@\[\]\\^_`{|}~])/,autolink:/^<(scheme:[^\s\x00-\x1f<>]*|email)>/,url:g,tag:"^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^",link:/^!?\[(label)\]\(href(?:\s+(title))?\s*\)/,reflink:/^!?\[(label)\]\[(?!\s*\])((?:\\[\[\]]?|[^\[\]\\])+)\]/,nolink:/^!?\[(?!\s*\])((?:\[[^\[\]]*\]|\\[\[\]]|[^\[\]])*)\](?:\[\])?/,strong:/^__([^\s])__(?!_)|^\*\*([^\s])\*\*(?!\*)|^__([^\s][\s\S]*?[^\s])__(?!_)|^\*\*([^\s][\s\S]*?[^\s])\*\*(?!\*)/,em:/^_([^\s_])_(?!_)|^\*([^\s*"<\[])\*(?!\*)|^_([^\s][\s\S]*?[^\s_])_(?!_)|^_([^\s_][\s\S]*?[^\s])_(?!_)|^\*([^\s"<\[][\s\S]*?[^\s*])\*(?!\*)|^\*([^\s*"<\[][\s\S]*?[^\s])\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`]?)\s*\1(?!`)/,br:/^( {2,}|\\)\n(?!\s*$)/,del:g,text:/^[\s\S]+?(?=[\\/g,">").replace(/"/g,""").replace(/'/g,"'")}function c(e){return e.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi,function(e,t){return"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""})}function t(n,e){return n=n.source||n,e=e||"",{replace:function(e,t){return t=(t=t.source||t).replace(/(^|[^\[])\^/g,"$1"),n=n.replace(e,t),this},getRegex:function(){return new RegExp(n,e)}}}function i(e,t){return l[" "+e]||(/^[^:]+:\/*[^/]*$/.test(e)?l[" "+e]=e+"/":l[" "+e]=y(e,"/",!0)),e=l[" "+e],"//"===t.slice(0,2)?e.replace(/:[\s\S]*/,":")+t:"/"===t.charAt(0)?e.replace(/(:\/*[^/]*)[\s\S]*/,"$1")+t:e+t}n._escapes=/\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/g,n._scheme=/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/,n._email=/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/,n.autolink=t(n.autolink).replace("scheme",n._scheme).replace("email",n._email).getRegex(),n._attribute=/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/,n.tag=t(n.tag).replace("comment",k._comment).replace("attribute",n._attribute).getRegex(),n._label=/(?:\[[^\[\]]*\]|\\[\[\]]?|`[^`]*`|[^\[\]\\])*?/,n._href=/\s*(<(?:\\[<>]?|[^\s<>\\])*>|(?:\\[()]?|\([^\s\x00-\x1f\\]*\)|[^\s\x00-\x1f()\\])*?)/,n._title=/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/,n.link=t(n.link).replace("label",n._label).replace("href",n._href).replace("title",n._title).getRegex(),n.reflink=t(n.reflink).replace("label",n._label).getRegex(),n.normal=f({},n),n.pedantic=f({},n.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,link:t(/^!?\[(label)\]\((.*?)\)/).replace("label",n._label).getRegex(),reflink:t(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label",n._label).getRegex()}),n.gfm=f({},n.normal,{escape:t(n.escape).replace("])","~|])").getRegex(),url:t(/^((?:ftp|https?):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("email",n._email).getRegex(),_backpedal:/(?:[^?!.,:;*_~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_~)]+(?!$))+/,del:/^~+(?=\S)([\s\S]*?\S)~+/,text:t(n.text).replace("]|","~]|").replace("|","|https?://|ftp://|www\\.|[a-zA-Z0-9.!#$%&'*+/=?^_`{\\|}~-]+@|").getRegex()}),n.breaks=f({},n.gfm,{br:t(n.br).replace("{2,}","*").getRegex(),text:t(n.gfm.text).replace("{2,}","*").getRegex()}),h.rules=n,h.output=function(e,t,n){return new h(t,n).output(e)},h.prototype.output=function(e){for(var t,n,r,s,i,l,o="";e;)if(i=this.rules.escape.exec(e))e=e.substring(i[0].length),o+=i[1];else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),r="@"===i[2]?"mailto:"+(n=u(this.mangle(i[1]))):n=u(i[1]),o+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.tag.exec(e))!this.inLink&&/^/i.test(i[0])&&(this.inLink=!1),e=e.substring(i[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(i[0]):u(i[0]):i[0];else if(i=this.rules.link.exec(e))e=e.substring(i[0].length),this.inLink=!0,r=i[2],this.options.pedantic?(t=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(r))?(r=t[1],s=t[3]):s="":s=i[3]?i[3].slice(1,-1):"",r=r.trim().replace(/^<([\s\S]*)>$/,"$1"),o+=this.outputLink(i,{href:h.escapes(r),title:h.escapes(s)}),this.inLink=!1;else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\s+/g," "),!(t=this.links[t.toLowerCase()])||!t.href){o+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),o+=this.renderer.strong(this.output(i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),o+=this.renderer.em(this.output(i[6]||i[5]||i[4]||i[3]||i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),o+=this.renderer.codespan(u(i[2].trim(),!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),o+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),o+=this.renderer.del(this.output(i[1]));else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),o+=this.renderer.text(u(this.smartypants(i[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else{for(;l=i[0],i[0]=this.rules._backpedal.exec(i[0])[0],l!==i[0];);e=e.substring(i[0].length),"@"===i[2]?r="mailto:"+(n=u(i[0])):(n=u(i[0]),r="www."===i[1]?"http://"+n:n),o+=this.renderer.link(r,null,n)}return o},h.escapes=function(e){return e?e.replace(h.rules._escapes,"$1"):e},h.prototype.outputLink=function(e,t){var n=t.href,r=t.title?u(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,u(e[1]))},h.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},h.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",r=e.length,s=0;s'+(n?e:u(e,!0))+"\n":"
"+(n?e:u(e,!0))+"
"},r.prototype.blockquote=function(e){return"
\n"+e+"
\n"},r.prototype.html=function(e){return e},r.prototype.heading=function(e,t,n){return this.options.headerIds?"'+e+"\n":""+e+"\n"},r.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},r.prototype.list=function(e,t,n){var r=t?"ol":"ul";return"<"+r+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"},r.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},r.prototype.checkbox=function(e){return" "},r.prototype.paragraph=function(e){return"

    "+e+"

    \n"},r.prototype.table=function(e,t){return t&&(t=""+t+""),"\n\n"+e+"\n"+t+"
    \n"},r.prototype.tablerow=function(e){return"\n"+e+"\n"},r.prototype.tablecell=function(e,t){var n=t.header?"th":"td";return(t.align?"<"+n+' align="'+t.align+'">':"<"+n+">")+e+"\n"},r.prototype.strong=function(e){return""+e+""},r.prototype.em=function(e){return""+e+""},r.prototype.codespan=function(e){return""+e+""},r.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},r.prototype.del=function(e){return""+e+""},r.prototype.link=function(e,t,n){if(this.options.sanitize){try{var r=decodeURIComponent(c(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return n}if(0===r.indexOf("javascript:")||0===r.indexOf("vbscript:")||0===r.indexOf("data:"))return n}this.options.baseUrl&&!o.test(e)&&(e=i(this.options.baseUrl,e));try{e=encodeURI(e).replace(/%25/g,"%")}catch(e){return n}var s='
    "},r.prototype.image=function(e,t,n){this.options.baseUrl&&!o.test(e)&&(e=i(this.options.baseUrl,e));var r=''+n+'":">"},r.prototype.text=function(e){return e},s.prototype.strong=s.prototype.em=s.prototype.codespan=s.prototype.del=s.prototype.text=function(e){return e},s.prototype.link=s.prototype.image=function(e,t,n){return""+n},s.prototype.br=function(){return""},p.parse=function(e,t){return new p(t).parse(e)},p.prototype.parse=function(e){this.inline=new h(e.links,this.options),this.inlineText=new h(e.links,f({},this.options,{renderer:new s})),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},p.prototype.next=function(){return this.token=this.tokens.pop()},p.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},p.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},p.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,c(this.inlineText.output(this.token.text)));case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,r,s="",i="";for(n="",e=0;et)n.splice(t);else for(;n.lengthAn error occurred:

    "+u(e.message+"",!0)+"
    ";throw e}}g.exec=g,d.options=d.setOptions=function(e){return f(d.defaults,e),d},d.getDefaults=function(){return{baseUrl:null,breaks:!1,gfm:!0,headerIds:!0,headerPrefix:"",highlight:null,langPrefix:"language-",mangle:!0,pedantic:!1,renderer:new r,sanitize:!1,sanitizer:null,silent:!1,smartLists:!1,smartypants:!1,tables:!0,xhtml:!1}},d.defaults=d.getDefaults(),d.Parser=p,d.parser=p.parse,d.Renderer=r,d.TextRenderer=s,d.Lexer=a,d.lexer=a.lex,d.InlineLexer=h,d.inlineLexer=h.output,d.parse=d,"undefined"!=typeof module&&"object"==typeof exports?module.exports=d:"function"==typeof define&&define.amd?define(function(){return d}):e.marked=d}(this||("undefined"!=typeof window?window:global)); -------------------------------------------------------------------------------- /blog/vendor/pace-1.2.4.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * pace.js v1.2.4 3 | * https://github.com/CodeByZach/pace/ 4 | * Licensed MIT © HubSpot, Inc. 5 | */ 6 | !function(){function o(t,e){return function(){return t.apply(e,arguments)}}var u,c,i,s,n,y,t,l,v,r,a,p,e,h,w,b,f,g,d,m,k,S,q,L,x,P,T,R,j,O,E,M,A,C,N,_,F,U,W,X,D,H,I,z,G,B,J=[].slice,K={}.hasOwnProperty,Q=function(t,e){for(var n in e)K.call(e,n)&&(t[n]=e[n]);function r(){this.constructor=t}return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t},V=[].indexOf||function(t){for(var e=0,n=this.length;e\n
    \n
    \n
    ',null!=t.firstChild?t.insertBefore(this.el,t.firstChild):t.appendChild(this.el)}return this.el},$.prototype.finish=function(){var t=this.getElement();return t.className=t.className.replace("pace-active","pace-inactive"),document.body.className=document.body.className.replace("pace-running ","pace-done ")},$.prototype.update=function(t){return this.progress=t,y.trigger("progress",t),this.render()},$.prototype.destroy=function(){try{this.getElement().parentNode.removeChild(this.getElement())}catch(t){n=t}return this.el=void 0},$.prototype.render=function(){var t,e,n,r,s,o,i;if(null==document.querySelector(T.target))return!1;for(t=this.getElement(),r="translate3d("+this.progress+"%, 0, 0)",s=0,o=(i=["webkitTransform","msTransform","transform"]).length;sT.eventLag.sampleCount&&o.shift(),e=h(o),++s>=T.eventLag.minSamples&&ethis.progress&&(this.progress+=this.catchup*t),e=1-Math.pow(this.progress/100,T.easeFactor),this.progress+=e*this.rate*t,this.progress=Math.min(this.lastProgress+T.maxProgressPerFrame,this.progress),this.progress=Math.max(0,this.progress),this.progress=Math.min(100,this.progress),this.lastProgress=this.progress,this.progress},v=it,b=e=_=w=E=N=null,y.running=!1,q=function(){if(T.restartOnPushState)return y.restart()},null!=window.history.pushState&&(I=window.history.pushState,window.history.pushState=function(){return q(),I.apply(window.history,arguments)}),null!=window.history.replaceState&&(G=window.history.replaceState,window.history.replaceState=function(){return q(),G.apply(window.history,arguments)}),l={ajax:u,elements:k,document:B,eventLag:Q},(x=function(){var t,e,n,r,s,o,i,a;for(y.sources=N=[],e=0,r=(o=["ajax","elements","document","eventLag"]).length;e 4 | based on dark.css by Ivan Sagalaev 5 | 6 | */ 7 | 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | background: #3f3f3f; 13 | color: #dcdcdc; 14 | } 15 | 16 | .hljs-keyword, 17 | .hljs-selector-tag, 18 | .hljs-tag { 19 | color: #e3ceab; 20 | } 21 | 22 | .hljs-template-tag { 23 | color: #dcdcdc; 24 | } 25 | 26 | .hljs-number { 27 | color: #8cd0d3; 28 | } 29 | 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-attribute { 33 | color: #efdcbc; 34 | } 35 | 36 | .hljs-literal { 37 | color: #efefaf; 38 | } 39 | 40 | .hljs-subst { 41 | color: #8f8f8f; 42 | } 43 | 44 | .hljs-title, 45 | .hljs-name, 46 | .hljs-selector-id, 47 | .hljs-selector-class, 48 | .hljs-section, 49 | .hljs-type { 50 | color: #efef8f; 51 | } 52 | 53 | .hljs-symbol, 54 | .hljs-bullet, 55 | .hljs-link { 56 | color: #dca3a3; 57 | } 58 | 59 | .hljs-deletion, 60 | .hljs-string, 61 | .hljs-built_in, 62 | .hljs-builtin-name { 63 | color: #cc9393; 64 | } 65 | 66 | .hljs-addition, 67 | .hljs-comment, 68 | .hljs-quote, 69 | .hljs-meta { 70 | color: #7f9f7f; 71 | } 72 | 73 | 74 | .hljs-emphasis { 75 | font-style: italic; 76 | } 77 | 78 | .hljs-strong { 79 | font-weight: bold; 80 | } 81 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/**" 5 | ], 6 | "scripts": { 7 | "lint": "eslint .", 8 | "lint:fix": "eslint . --fix", 9 | "release": "cd packages/silent && np patch --no-tests --branch=2x", 10 | "deploy": "run-s sync && gh-pages -d blog", 11 | "sync": "run-p sync:readme:packages sync:readme:blog && run-s sync:blog", 12 | "sync:blog": "rm -rf packages/silent/blog && cp -r blog packages/silent/ && rm packages/silent/blog/.eslintrc.js", 13 | "sync:readme:blog": "cat README.md | jayin -ti -to 'x.replaceAll(`https://github.com/fritx/silent/tree/1x`, `../silent/`).replaceAll(`https://blog.fritx.me/?`, `?`).replaceAll(`https://fritx.github.io/silent/?`, `?`).replaceAll(`https://fritx.github.io/silent/p/`, `../../`)' > blog/p/projects/silent_2.0/README.md", 14 | "sync:readme:packages": "cp README.md packages/silent/ && cp README.md packages/create-silent/" 15 | }, 16 | "devDependencies": { 17 | "eslint": "^8.25.0", 18 | "eslint-config-fritx": "^0.2.4", 19 | "eslint-plugin-es5": "^1.5.0", 20 | "gh-pages": "^4.0.0", 21 | "jayin": "^0.0.3", 22 | "np": "^8.0.4", 23 | "npm-run-all": "^4.1.5" 24 | }, 25 | "homepage": "https://github.com/fritx/silent", 26 | "repository": "git@github.com:fritx/silent.git", 27 | "license": "MIT" 28 | } 29 | -------------------------------------------------------------------------------- /packages/create-silent/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | require('silent/cli') 3 | -------------------------------------------------------------------------------- /packages/create-silent/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-silent", 3 | "version": "0.0.2", 4 | "description": "Be a silent, static blog", 5 | "keywords": [ 6 | "blog", 7 | "static", 8 | "template", 9 | "site", 10 | "silentor", 11 | "silent" 12 | ], 13 | "homepage": "https://github.com/fritx/silent", 14 | "repository": "git@github.com:fritx/silent.git", 15 | "license": "MIT", 16 | "bin": "cli.js", 17 | "engines": { 18 | "node": ">=8.0.0" 19 | }, 20 | "dependencies": { 21 | "silent": "^0.2.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/silent/cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | let silent = require('.') 3 | let argv = process.argv 4 | 5 | ;(async () => { 6 | let [action, ...args] = argv.slice(2) 7 | if (argv[1].endsWith('create-silent')) { 8 | action = 'create' 9 | args = argv.slice(2) 10 | } 11 | 12 | let allowList = ['create'] 13 | if (!allowList.includes(action)) { 14 | throw new Error(`warn: '${action}' action not found.\nvisit https://github.com/fritx/silent`) 15 | } 16 | 17 | await silent.create(...args) 18 | console.log(`silent-${action} completed`) 19 | })().catch(err => { 20 | if (/\bverbose:/.test(err)) { 21 | return 22 | } 23 | if (/\bwarn:/.test(err)) { 24 | console.error(err.message) 25 | return 26 | } 27 | throw err 28 | }) 29 | -------------------------------------------------------------------------------- /packages/silent/index.js: -------------------------------------------------------------------------------- 1 | let prompts = require('prompts') 2 | let shell = require('shelljs') 3 | let { resolve } = require('path') 4 | 5 | let beforeCreate = async dest => { 6 | if (!shell.test('-e', dest)) { 7 | shell.mkdir('-p', dest) 8 | return 9 | } 10 | if (!shell.test('-d', dest)) { 11 | throw new Error('dest should be a directory') 12 | } 13 | let { confirm } = await prompts({ 14 | type: 'text', 15 | name: 'confirm', 16 | message: 'dest already exists, are you sure to apply onto it? (Y/n)' 17 | }) 18 | if (confirm !== 'Y') { 19 | throw new Error('warn: you cancelled') 20 | } 21 | } 22 | 23 | exports.create = async _dest => { 24 | if (!_dest) { 25 | throw new Error('warn: usage:\n$ npm create silent # opt.1\n$ silent create # opt.2') 26 | } 27 | let dest = resolve(process.cwd(), _dest) 28 | await beforeCreate(dest) 29 | let blogDir = resolve(__dirname, 'blog') 30 | console.log('copying', blogDir) 31 | console.log(' =>', dest) 32 | shell.cp('-rL', blogDir + '/*', dest) 33 | } 34 | -------------------------------------------------------------------------------- /packages/silent/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "silent", 3 | "version": "0.2.3", 4 | "description": "Be a silent, static blog", 5 | "keywords": [ 6 | "blog", 7 | "static", 8 | "template", 9 | "site", 10 | "silentor", 11 | "silent" 12 | ], 13 | "homepage": "https://github.com/fritx/silent", 14 | "repository": "git@github.com:fritx/silent.git", 15 | "license": "MIT", 16 | "bin": "cli.js", 17 | "main": "index.js", 18 | "scripts": { 19 | "test": "test -d blog" 20 | }, 21 | "engines": { 22 | "node": ">=8.0.0" 23 | }, 24 | "dependencies": { 25 | "prompts": "^2.4.2", 26 | "shelljs": "^0.8.5" 27 | } 28 | } 29 | --------------------------------------------------------------------------------