├── .gitignore ├── 404.html ├── CNAME ├── Gemfile ├── Gruntfile.js ├── LICENSE ├── README.md ├── Rakefile ├── _config.yml ├── _doc ├── Manual.md └── README.zh.md ├── _includes ├── about │ ├── en.md │ └── zh.md ├── ads.html ├── featured-tags.html ├── footer.html ├── friends.html ├── head.html ├── intro-header.html ├── mathjax_support.html ├── multilingual-sel.html ├── nav.html ├── posts │ └── 2017-07-12-upgrading-eleme-to-pwa │ │ ├── en.md │ │ └── zh.md ├── search.html ├── short-about.html └── sns-links.html ├── _layouts ├── default.html ├── keynote.html ├── page.html └── post.html ├── _posts ├── 2014-01-29-hello-2015.markdown ├── 2014-08-16-miui6.markdown ├── 2014-09-04-is-pure-android-better.markdown ├── 2014-10-01-why-alibaba-ux-sucks.markdown ├── 2014-11-20-responsive-web-design.markdown ├── 2014-12-13-wechat-block-kuaidi.markdown ├── 2015-03-10-apple-event-2015.markdown ├── 2015-03-25-digital-native.markdown ├── 2015-03-31-e2e_user_scenarios.markdown ├── 2015-04-14-unix-linux-note.markdown ├── 2015-04-15-os-metro.markdown ├── 2015-05-11-see-u-ali.markdown ├── 2015-05-25-js-module-loader.markdown ├── 2015-06-15-alitrip-strategy.markdown ├── 2015-07-09-js-module-7day.markdown ├── 2015-09-22-js-version.markdown ├── 2015-10-28-how-designer-learn-fe.markdown ├── 2015-12-15-ios9-safari-web.markdown ├── 2015-12-28-css-sucks-2015.markdown ├── 2016-02-01-React-vs-Angular2.markdown ├── 2016-06-05-pwa-in-my-pov.markdown ├── 2016-09-22-the-open-web.md ├── 2016-10-20-pwa-qcon2016.markdown ├── 2016-11-20-sw-101-gdgdf.markdown ├── 2017-01-09-wechat-miniapp-ux.md ├── 2017-02-09-nextgen-web-pwa.markdown ├── 2017-04-06-html-document.md ├── 2017-05-28-sw-precache.md ├── 2017-06-25-you-are-slaves.markdown ├── 2017-07-12-upgrading-eleme-to-pwa.markdown ├── 2017-07-26-farewell-flash.md ├── 2017-10-06-css-complaints.md ├── 2017-12-12-halting-problem.md ├── 2017-12-12-uncomputable-funcs.md ├── 2018-05-11-pwa-zh-preface.md ├── 2018-06-30-dreamer.md ├── 2018-09-27-avoiding-success-at-all-cost.md ├── 2018-10-06-vim-cn-im.md ├── 2019-09-03-vim-from-finder.md ├── 2019-09-08-spacemacs-workflow.md ├── 2019-11-19-is-pwa-dead-in-2019.md ├── 2020-04-03-react-hooks-vue-composition.md ├── 2020-07-05-reflection-2020.md ├── 2021-01-19-the-systematic-failure-of-higher-education-in-china.md ├── 2021-04-10-js-20yrs-preface.md ├── cs_idols │ └── 2019-09-13-peter-john-landin.md ├── data_rep │ ├── 2020-06-19-data-rep-int.md │ ├── 2020-06-21-data-rep-float.md │ └── 2020-06-21-data-rep-todo.md ├── hidden │ └── 2020-05-05-pl-chart.md ├── read_sf_lf │ ├── 2019-01-01-sf-lf-01-basics.md │ ├── 2019-01-02-sf-lf-02-induction.md │ ├── 2019-01-03-sf-lf-03-list.md │ ├── 2019-01-04-sf-lf-04-poly.md │ ├── 2019-01-05-sf-lf-05-tactics.md │ ├── 2019-01-06-sf-lf-06-logic.md │ ├── 2019-01-07-sf-lf-07-indprop.md │ ├── 2019-01-08-sf-lf-08-map.md │ ├── 2019-01-09-sf-lf-09-proof-object.md │ ├── 2019-01-10-sf-lf-10-ind-principle.md │ ├── 2019-01-11-sf-lf-11-rel.md │ ├── 2019-01-12-sf-lf-12-imp.md │ ├── 2019-01-13-sf-lf-13-imp-parser.md │ ├── 2019-01-14-sf-lf-14-imp-ceval.md │ ├── 2019-01-15-sf-lf-15-extraction.md │ └── 2019-01-16-sf-lf-16-auto.md ├── read_sf_plf │ ├── 2019-03-01-sf-plf-01-equiv.md │ ├── 2019-03-02-sf-plf-02-hoare-1.md │ ├── 2019-03-03-sf-plf-03-hoare-2.md │ ├── 2019-03-04-sf-plf-04-hoare-logic.md │ ├── 2019-03-05-sf-plf-05-smallstep.md │ ├── 2019-03-06-sf-plf-06-types.md │ ├── 2019-03-07-sf-plf-07-STLC.md │ ├── 2019-03-08-sf-plf-08-STLC-prop.md │ ├── 2019-03-09-sf-plf-09-more-STLC.md │ ├── 2019-03-10-sf-plf-10-subtyping.md │ ├── 2019-03-11-sf-plf-11-typechecking.md │ ├── 2019-03-12-sf-plf-12-records.md │ ├── 2019-03-13-sf-plf-13-references.md │ ├── 2019-03-14-sf-plf-14-record-sub.md │ ├── 2019-03-15-sf-plf-15-norm-STLC.md │ ├── 2019-03-16-sf-plf-16-lib-tactics.md │ ├── 2019-03-17-sf-plf-17-use-tactics.md │ ├── 2019-03-18-sf-plf-18-use-auto.md │ └── 2019-03-19-sf-plf-19-partial-eval.md └── read_sf_qc │ └── 2019-09-02-sf-qc-02-typeclasses.md ├── about.html ├── ads.txt ├── archive.html ├── css ├── bootstrap.css ├── bootstrap.min.css ├── hux-blog.css └── hux-blog.min.css ├── feed.xml ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff └── glyphicons-halflings-regular.woff2 ├── img ├── 404-bg.jpg ├── avatar-hux-home.jpg ├── avatar-hux-ny.jpg ├── avatar-hux.jpg ├── bg-little-universe.jpg ├── bg-material.jpg ├── bg-me-2022.jpg ├── bg-walle.jpg ├── blog-desktop.jpg ├── blog-keynote.jpg ├── blog-md-navbar.gif ├── blog-sidebar.jpg ├── contact-bg.jpg ├── favicon.ico ├── home-bg-art.jpg ├── home-bg-geek.jpg ├── home-bg-o.jpg ├── home-bg.jpg ├── icon_wechat.png ├── in-post │ ├── forcify.jpg │ ├── open-source-license.png │ ├── post-alitrip-pd │ │ ├── post-alitrip-pd.013.jpg │ │ ├── post-alitrip-pd.014.jpg │ │ ├── post-alitrip-pd.016.jpg │ │ ├── post-alitrip-pd.018.jpg │ │ ├── post-alitrip-pd.019.jpg │ │ ├── post-alitrip-pd.020.jpg │ │ ├── post-alitrip-pd.021.jpg │ │ ├── post-alitrip-pd.023.jpg │ │ ├── post-alitrip-pd.026.jpg │ │ ├── post-alitrip-pd.028.jpg │ │ ├── post-alitrip-pd.029.jpg │ │ ├── post-alitrip-pd.030.jpg │ │ └── post-alitrip-pd.031.jpg │ ├── post-c-u-ali-079717.png │ ├── post-c-u-ali-memo.jpg │ ├── post-c-u-ali-team.png │ ├── post-eleme-pwa │ │ ├── Architecture.png │ │ ├── Lighthouse-after.png │ │ ├── Lighthouse-before.png │ │ ├── PRECACHE-future-routes.jpg │ │ ├── PUSH-link-rel-preload.jpg │ │ ├── after-skeleton.jpg │ │ ├── before-skeleton.jpg │ │ ├── eleme-at-io.jpg │ │ ├── msite-After-Optim.png │ │ ├── msite-Before-Optim.png │ │ ├── nextTick-&-Load.png │ │ └── thisTick-&-Load.png │ ├── post-f-f-weibo.png │ ├── post-js-version │ │ ├── javascript-java.jpg │ │ └── keep-calm-and-learn-javascript.png │ ├── post-kuaidi-1.jpg │ ├── post-kuaidi-2.jpg │ ├── post-metro-panorama.jpg │ ├── post-metro-real.jpg │ ├── post-metro-ui.jpg │ ├── post-nextgen-web-pwa │ │ ├── PWAR-007.jpeg │ │ ├── PWAR-014+PWA.jpeg │ │ ├── flipkart-1.jpeg │ │ ├── flipkart-2.jpeg │ │ ├── flipkart-3.jpeg │ │ ├── ios2-a2hs.gif │ │ ├── qcon-hybridzation.png │ │ ├── qcon-trend.png │ │ ├── sw-lifecycle.png │ │ ├── sw-race.png │ │ └── sw-sw.png │ └── post-wmu │ │ ├── maoyan.jpg │ │ ├── question.jpg │ │ └── wepiao.jpg ├── post-bg-2015.jpg ├── post-bg-alibaba.jpg ├── post-bg-alitrip.jpg ├── post-bg-android.jpg ├── post-bg-apple-event-2015.jpg ├── post-bg-css.jpg ├── post-bg-digital-native.jpg ├── post-bg-dreamer.jpg ├── post-bg-e2e-ux.jpg ├── post-bg-farewell-flash.jpg ├── post-bg-halting.jpg ├── post-bg-infinity.jpg ├── post-bg-ios9-web.jpg ├── post-bg-js-module.jpg ├── post-bg-js-version.jpg ├── post-bg-kuaidi.jpg ├── post-bg-miui-ux.jpg ├── post-bg-miui6.jpg ├── post-bg-nextgen-web-pwa.jpg ├── post-bg-os-metro.jpg ├── post-bg-re-vs-ng2.jpg ├── post-bg-rwd.jpg ├── post-bg-see-u-ali.jpg ├── post-bg-universe.jpg ├── post-bg-unix-linux.jpg ├── post-bg-web.jpg └── post-sample-image.jpg ├── index.html ├── js ├── animatescroll.min.js ├── archive.js ├── bootstrap.js ├── bootstrap.min.js ├── hux-blog.js ├── hux-blog.min.js ├── jquery.js ├── jquery.min.js ├── jquery.nav.js ├── jquery.tagcloud.js ├── simple-jekyll-search.min.js ├── snackbar.js └── sw-registration.js ├── less ├── highlight.less ├── hux-blog.less ├── mixins.less ├── search.less ├── side-catalog.less ├── sidebar.less ├── snackbar.less └── variables.less ├── offline.html ├── package-lock.json ├── package.json ├── pwa ├── icons │ ├── 128.png │ └── 512.png └── manifest.json ├── search.json └── sw.js /.gitignore: -------------------------------------------------------------------------------- 1 | _site 2 | _posts/_draft 3 | _posts/_archive 4 | _archive 5 | node_modules 6 | .vscode 7 | *.log 8 | *.lock 9 | *.sh 10 | .DS_Store 11 | .jekyll-cache 12 | */.DS_Store 13 | */*/.DS_Store 14 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: 404 4 | hide-in-nav: true 5 | description: "你来到了没有知识的荒原 :(" 6 | header-img: "img/404-bg.jpg" 7 | permalink: /404.html 8 | --- 9 | 10 | 11 | <!-- Page Header --> 12 | {% include intro-header.html type="page" short='true' %} 13 | 14 | <script> 15 | document.body.classList.add('page-fullscreen'); 16 | </script> 17 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | huangxuan.me 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'jekyll-paginate' 3 | 4 | gem "jekyll", "~> 4.0" 5 | gem "rake" 6 | 7 | gem "webrick", "~> 1.7" 8 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | // Project configuration. 4 | grunt.initConfig({ 5 | pkg: grunt.file.readJSON('package.json'), 6 | uglify: { 7 | main: { 8 | src: 'js/<%= pkg.name %>.js', 9 | dest: 'js/<%= pkg.name %>.min.js' 10 | } 11 | }, 12 | less: { 13 | expanded: { 14 | options: { 15 | paths: ["css"] 16 | }, 17 | files: { 18 | "css/<%= pkg.name %>.css": "less/<%= pkg.name %>.less" 19 | } 20 | }, 21 | minified: { 22 | options: { 23 | paths: ["css"], 24 | cleancss: true 25 | }, 26 | files: { 27 | "css/<%= pkg.name %>.min.css": "less/<%= pkg.name %>.less" 28 | } 29 | } 30 | }, 31 | banner: '/*!\n' + 32 | ' * <%= pkg.title %> v<%= pkg.version %> (<%= pkg.homepage %>)\n' + 33 | ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + 34 | ' */\n', 35 | usebanner: { 36 | dist: { 37 | options: { 38 | position: 'top', 39 | banner: '<%= banner %>' 40 | }, 41 | files: { 42 | src: ['css/<%= pkg.name %>.css', 'css/<%= pkg.name %>.min.css', 'js/<%= pkg.name %>.min.js'] 43 | } 44 | } 45 | }, 46 | watch: { 47 | scripts: { 48 | files: ['js/<%= pkg.name %>.js'], 49 | tasks: ['uglify'], 50 | options: { 51 | spawn: false, 52 | }, 53 | }, 54 | less: { 55 | files: ['less/*.less'], 56 | tasks: ['less'], 57 | options: { 58 | spawn: false, 59 | } 60 | }, 61 | }, 62 | }); 63 | 64 | // Load the plugins. 65 | grunt.loadNpmTasks('grunt-contrib-uglify'); 66 | grunt.loadNpmTasks('grunt-contrib-less'); 67 | grunt.loadNpmTasks('grunt-banner'); 68 | grunt.loadNpmTasks('grunt-contrib-watch'); 69 | 70 | // Default task(s). 71 | grunt.registerTask('default', ['uglify', 'less', 'usebanner']); 72 | 73 | }; 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Hux Blog](https://huangxuan.me) 2 | ================================ 3 | 4 | > I never expected this to become popular. 5 | 6 |  7 | 8 | 9 | [User Manual 👉](_doc/Manual.md) 10 | -------------------------------------------------- 11 | 12 | ### Getting Started 13 | 14 | 1. You will need [Ruby](https://www.ruby-lang.org/en/) and [Bundler](https://bundler.io/) to use [Jekyll](https://jekyllrb.com/). Following [Using Jekyll with Bundler](https://jekyllrb.com/tutorials/using-jekyll-with-bundler/) to fullfill the enviromental requirement. 15 | 16 | 2. Installed dependencies in the `Gemfile`: 17 | 18 | ```sh 19 | $ bundle install 20 | ``` 21 | 22 | 3. Serve the website (`localhost:4000` by default): 23 | 24 | ```sh 25 | $ bundle exec jekyll serve # alternatively, npm start 26 | ``` 27 | 28 | ### Development (Build From Source) 29 | 30 | To modify the theme, you will need [Grunt](https://gruntjs.com/). There are numbers of tasks you can find in the `Gruntfile.js`, includes minifing JavaScript, compiling `.less` to `.css`, adding banners to keep the Apache 2.0 license intact, watching for changes, etc. 31 | 32 | Yes, they were inherited and are extremely old-fashioned. There is no modularization and transpilation, etc. 33 | 34 | Critical Jekyll-related code are located in `_include/` and `_layouts/`. Most of them are [Liquid](https://github.com/Shopify/liquid/wiki) templates. 35 | 36 | This theme uses the default code syntax highlighter of jekyll, [Rouge](http://rouge.jneen.net/), which is compatible with Pygments theme so just pick any pygments theme css (e.g. from [here](http://jwarby.github.io/jekyll-pygments-themes/languages/javascript.html) and replace the content of `highlight.less`. 37 | 38 | 39 | ### Interesting to know more? Checkout the [full user manual](_doc/Manual.md)! 40 | 41 | 42 | Other Resources 43 | --------------- 44 | 45 | Ports 46 | - [**Hexo**](https://github.com/Kaijun/hexo-theme-huxblog) by @kaijun 47 | - [**React-SSR**](https://github.com/LucasIcarus/huxpro.github.io/tree/ssr) by @LucasIcarus 48 | 49 | [Starter/Boilerplate](https://github.com/huxpro/huxblog-boilerplate) 50 | - Out of date. Helps wanted for updating it on par with the main repo 51 | 52 | Translation 53 | - [🇨🇳 中文文档(有点过时)](https://github.com/Huxpro/huxpro.github.io/blob/master/_doc/README.zh.md) 54 | 55 | 56 | License 57 | ------- 58 | 59 | Apache License 2.0. 60 | Copyright (c) 2015-present Huxpro 61 | 62 | Hux Blog is derived from [Clean Blog Jekyll Theme (MIT License)](https://github.com/BlackrockDigital/startbootstrap-clean-blog-jekyll/) 63 | Copyright (c) 2013-2016 Blackrock Digital LLC. 64 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "rubygems" 2 | require 'rake' 3 | require 'yaml' 4 | require 'time' 5 | 6 | SOURCE = "." 7 | CONFIG = { 8 | 'version' => "12.3.2", 9 | 'themes' => File.join(SOURCE, "_includes", "themes"), 10 | 'layouts' => File.join(SOURCE, "_layouts"), 11 | 'posts' => File.join(SOURCE, "_posts"), 12 | 'post_ext' => "md", 13 | 'theme_package_version' => "0.1.0" 14 | } 15 | 16 | # Usage: rake post title="A Title" subtitle="A sub title" 17 | desc "Begin a new post in #{CONFIG['posts']}" 18 | task :post do 19 | abort("rake aborted: '#{CONFIG['posts']}' directory not found.") unless FileTest.directory?(CONFIG['posts']) 20 | title = ENV["title"] || "new-post" 21 | subtitle = ENV["subtitle"] || "This is a subtitle" 22 | slug = title.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '') 23 | begin 24 | date = (ENV['date'] ? Time.parse(ENV['date']) : Time.now).strftime('%Y-%m-%d') 25 | rescue Exception => e 26 | puts "Error - date format must be YYYY-MM-DD, please check you typed it correctly!" 27 | exit -1 28 | end 29 | filename = File.join(CONFIG['posts'], "#{date}-#{slug}.#{CONFIG['post_ext']}") 30 | if File.exist?(filename) 31 | abort("rake aborted!") if ask("#{filename} already exists. Do you want to overwrite?", ['y', 'n']) == 'n' 32 | end 33 | 34 | puts "Creating new post: #{filename}" 35 | open(filename, 'w') do |post| 36 | post.puts "---" 37 | post.puts "layout: post" 38 | post.puts "title: \"#{title.gsub(/-/,' ')}\"" 39 | post.puts "subtitle: \"#{subtitle.gsub(/-/,' ')}\"" 40 | post.puts "date: #{date}" 41 | post.puts "author: \"Hux\"" 42 | post.puts "header-img: \"img/post-bg-2015.jpg\"" 43 | post.puts "tags: []" 44 | post.puts "---" 45 | end 46 | end # task :post 47 | 48 | desc "Launch preview environment" 49 | task :preview do 50 | system "jekyll --auto --server" 51 | end # task :preview 52 | 53 | #Load custom rake scripts 54 | Dir['_rake/*.rake'].each { |r| load r } 55 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Site settings 2 | title: Hux Blog 3 | SEOTitle: 黄玄的博客 | Hux Blog 4 | header-img: img/home-bg.jpg 5 | email: huxpro@gmail.com 6 | description: "这里是 @Hux黄玄 的个人博客,与你一起发现更大的世界 | 要做一个有 swag 的程序员" 7 | keyword: "黄玄, Hux黄玄, Hux, 鬼栈, huxpro, @huxpro, 黄玄的博客, Hux Blog, 博客, 个人网站, 互联网, Web, JavaScript, React, React Native, 前端, 设计" 8 | url: "https://huangxuan.me" # your host, for absolute URL 9 | baseurl: "" # for example, '/blog' if your blog hosted on 'host/blog' 10 | 11 | # Publish posts or collection documents with a future date. 12 | future: true 13 | 14 | # SNS settings 15 | RSS: false 16 | weibo_username: huxpro 17 | zhihu_username: huxpro 18 | github_username: huxpro 19 | twitter_username: huxpro 20 | #facebook_username: huxpro 21 | #linkedin_username: firstname-lastname-idxxxx 22 | 23 | # Build settings 24 | # from 2016, 'pygments' is unsupported on GitHub Pages. Use 'rouge' for highlighting instead. 25 | highlighter: rouge 26 | permalink: pretty 27 | paginate: 10 28 | exclude: 29 | [ 30 | "less", 31 | "node_modules", 32 | "Gruntfile.js", 33 | "package.json", 34 | "README.md", 35 | "README.zh.md", 36 | ] 37 | anchorjs: true # if you want to customize anchor. check out line:181 of `post.html` 38 | # If you have timezone issue (e.g. #68) in China, uncomment to use this: 39 | #timezone: CN 40 | 41 | # Gems 42 | # from PR#40, to support local preview for Jekyll 3.0 43 | # make sure you have this gem installed 44 | # `$ gem install jekyll-paginate` 45 | plugins: [jekyll-paginate] 46 | 47 | # Markdown settings 48 | # replace redcarpet to kramdown, 49 | # although redcarpet can auto highlight code, the lack of header-id make the catalog impossible, so I switch to kramdown 50 | # document: http://jekyllrb.com/docs/configuration/#kramdown 51 | markdown: kramdown 52 | kramdown: 53 | input: GFM # use Github Flavored Markdown !important 54 | syntax_highlighter_opts: 55 | span: 56 | line_numbers: false 57 | block: 58 | line_numbers: true 59 | start_line: 1 60 | 61 | # Disqus settings 62 | disqus_username: hux 63 | 64 | # Netease settings 65 | netease_comment: false 66 | 67 | # Analytics settings 68 | # Baidu Analytics 69 | # ba_track_id: [your track id] 70 | 71 | # Google Analytics 72 | ga_track_id: "UA-49627206-1" # Format: UA-xxxxxx-xx 73 | ga_domain: huangxuan.me 74 | 75 | # Sidebar settings 76 | sidebar: true # whether or not using Sidebar. 77 | sidebar-about-description: "要做一个有 swag 的程序员 <br> React Team @ Meta" 78 | sidebar-avatar: https://github.com/Huxpro.png # use absolute URL, seeing it's used in both `/` and `/about/` 79 | 80 | # Featured Tags 81 | featured-tags: true # whether or not using Feature-Tags 82 | featured-condition-size: 1 # A tag will be featured if the size of it is more than this condition value 83 | 84 | # Progressive Web Apps 85 | chrome-tab-theme-color: "#000000" 86 | service-worker: true 87 | 88 | # MathJax rendering for layout:page (e.g. post preview) 89 | page-mathjax: false 90 | 91 | # Friends 92 | friends: 93 | [ 94 | { title: "乱序(Midare)", href: "http://mida.re/" }, 95 | { title: "Ebn Zhang", href: "https://ebnbin.dev/" }, 96 | { title: "Kun Qian", href: "http://kunq.me" }, 97 | { title: "Sherry Woo", href: "https://sherrywoo.me/" }, 98 | { title: "SmdCn", href: "http://blog.smdcn.net" }, 99 | { title: "JiyinYiyong", href: "http://tiye.me/" }, 100 | { title: "DHong Say", href: "http://dhong.co" }, 101 | { title: "尹峰以为", href: "http://ingf.github.io/" }, 102 | ] 103 | -------------------------------------------------------------------------------- /_includes/about/en.md: -------------------------------------------------------------------------------- 1 | Hey, I am Huang, Xuan (a.k.a. _@huxpro_). I worked on the [React Team](https://beta.reactjs.org/community/meet-the-team#react-core) at <del>Facebook</del>Meta. 2 | 3 | I considered myself as a hybrid between a software engineer specifically into the programming languages theories and implementations domain (i.e. compiler, type system, type-based formal verification, virtual machine, runtime systems, garbage collection), and a creative technologiest deeply caring about many humanistic aspects (e.g. visual, sound, interaction) in UI and HCI in general. 4 | 5 | I also worked on the [Hermes JavaScript Engine](https://hermesengine.dev/), some other projects under the [Reality Labs (Research)](https://tech.fb.com/ar-vr/), and [ReasonML](https://reasonml.github.io/) (now [ReScript](https://rescript-lang.org/)) efforts at Meta (Facebook). 6 | 7 | In the past, I worked on [Alitrip (Fliggy)](https://www.alitrip.com/) mobile and web apps under the [Alibaba Group](https://en.wikipedia.org/wiki/Alibaba_Group), found and lead front-end infrastructure team at an unicorn startup company [Beijing Weiying (a.k.a. WePiao, now acquired by Maoyan)](https://www.crunchbase.com/organization/beijing-weiying-technology), and helped [Ele.me (now acquired by Alibaba)](https://en.wikipedia.org/wiki/Ele.me) to upgrade their mobile web site into [the first influential PWA (progressive web app) in China](https://medium.com/elemefe/upgrading-ele-me-to-progressive-web-app-2a446832e509). 8 | 9 | I studied BA, Digital Media Art at [Communication University of China](https://en.wikipedia.org/wiki/Communication_University_of_China) and MS, Computer Science (with a focus on programming languages, mainly supervised by [Prof. Matthew Fluet](https://www.cs.rit.edu/~mtf/)) at [Rochester Institute of Technology](https://en.wikipedia.org/wiki/Rochester_Institute_of_Technology). 10 | 11 | ##### Appearence 12 | 13 | - [React Labs: What We've Been Working On – June 2022][12] · React Blog · 2022 14 | - [React Without Memo][11] · [React Conf 2021](https://conf.reactjs.org/) 15 | - [Toward Hermes being the Default][11] · React Native Blog · 2021 16 | - React Native 0.64 with Hermes for iOS · [The RN Show Podcast Ep #5](https://www.callstack.com/podcast-react-native-show) · 2021 17 | - [Upgrading to Progressive Web Apps][9] · [JSConf China Shanghai 2017](http://2017.jsconf.cn/) 18 | - Building Progressive Web Apps · [CSDI Guangzhou 2017](http://www.csdisummit.com/) 19 | - The State of Progressive Web App · GDG IO Redux Beijing 2017 20 | - PWA Rehashing · Baidu HQ Beijing 2017 21 | - [Service Worker 101][5] · GDG DevFest Beijing 2016 22 | - [Progressive Web Apps][4] · QCon Shanghai 2016 23 | - Progressive Web App in my POV · GDG IO Redux Beijing 2016 24 | - [CSS Still Sucks 2015][2] · 2015 25 | - [JavaScript Modularization Journey][1] · 2015 26 | 27 | [1]: //huangxuan.me/2015/07/09/js-module-7day/ 28 | [2]: //huangxuan.me/2015/12/28/css-sucks-2015/ 29 | [3]: //huangxuan.me/2016/06/05/pwa-in-my-pov/ 30 | [4]: //huangxuan.me/2016/10/20/pwa-qcon2016/ 31 | [5]: //huangxuan.me/2016/11/20/sw-101-gdgdf/ 32 | [6]: https://yanshuo.io/assets/player/?deck=58ac8598b123db0067292f92 "PWA Rehashing" 33 | [7]: https://yanshuo.io/assets/player/?deck=593ad6fbfe88c2006a0a0d6d "The State of PWA" 34 | [8]: https://yanshuo.io/assets/player/?deck=594d673d570c357d0698a950 "Building PWA" 35 | [9]: //huangxuan.me/jsconfcn2017/ 36 | [10]: https://reactnative.dev/blog/2021/10/26/toward-hermes-being-the-default 37 | [11]: https://youtu.be/lGEMwh32soc 38 | [12]: https://reactjs.org/blog/2022/06/15/react-labs-what-we-have-been-working-on-june-2022.html 39 | -------------------------------------------------------------------------------- /_includes/about/zh.md: -------------------------------------------------------------------------------- 1 | Hey,我是黄玄(a.k.a. Hux, _@huxpro_),一个略懂计算机科学与艺术的斜杆不动青年,自诩是一个[广院](https://baike.baidu.com/item/%E4%B8%AD%E5%9B%BD%E4%BC%A0%E5%AA%92%E5%A4%A7%E5%AD%A6)数字媒体艺术系与 RIT 计算机科学系(师从 [Prof. Matthew Fluet](https://www.cs.rit.edu/~mtf/) 专攻编程语言)杂交出来的[黑客与画家](https://book.douban.com/subject/6021440/)。 2 | 3 | 现为 <del>Facebook</del> Meta 签约软件工程师,就职于开源技术<del>网红</del>团队 [React](https://beta.reactjs.org/community/meet-the-team#react-core),曾参与 [Hermes JavaScript 引擎](https://hermesengine.dev/),[ReasonML](https://reasonml.github.io/) (现 [ReScript](https://rescript-lang.org/)),以及 [Reality Labs](https://tech.fb.com/ar-vr/) 某保密项目等。在国内期间,曾被招募为阿里巴巴 · [阿里旅行(飞猪)](http://alitrip.com)· 前端工程师、微影时代 · 微票儿 · 前端基础设施工程团队负责人、[饿了么](https://ele.me/) · 大前端团队 · [PWA 顾问](https://medium.com/elemefe/upgrading-ele-me-to-progressive-web-app-2a446832e509) 等。 4 | 5 | 6 | 目前的物理活动范围主要在美帝纽约与硅谷,也想当个数字游<del>民</del>侠。虚拟分身日常出没于[微博](https://weibo.com/huxpro)、[知乎](https://www.zhihu.com/people/huxpro/pins/posts)、[B站](https://space.bilibili.com/43271611)、[Instagram](https://www.instagram.com/huxpro/)、[推特](https://twitter.com/Huxpro/)、[Github](https://github.com/huxpro) 等。 7 | 8 | 9 | ##### 技术演讲 10 | 11 | - [我的大前端世界观][20] · [FEDAY](https://fequan.com/2023/) · 2023 12 | - [前端已死,前端永生][21] · [掘金年度技术演讲](https://juejin.cn/meetings/talk2023) · 2023 13 | - [React 国情咨文 2022][13] · 第七届中国开源年会 · 2023 14 | - [React Labs: What We've Been Working On – June 2022][12] · React Blog 15 | - [React Without Memo][11] · [React Conf 2021](https://conf.reactjs.org/) 16 | - [Toward Hermes being the Default][11] · React Native Blog · 2021 17 | - React Native 0.64 with Hermes for iOS · [The RN Show Podcast Ep #5](https://www.callstack.com/podcast-react-native-show) · 2021 18 | - [Upgrading to Progressive Web Apps][9] · [Youtube](https://www.youtube.com/watch?v=RWzMF-1fjJ8&t=1s) · [JSConf CN 上海 2017](http://2017.jsconf.cn/) 19 | - Building Progressive Web Apps · [CSDI 广州 2017](http://www.csdisummit.com/) 20 | - The State of Progressive Web App · GDG IO Redux 北京 2017 21 | - 炒冷饭 · PWA 到底是个什么玩意?· Baidu HQ 北京 2017 22 | - [Service Worker 101][5] · GDG DevFest 北京 2016 23 | - [Progressive Web App,复兴序章][4] · [QCon 上海 2016](http://2016.qconshanghai.com/presentation/3111) 24 | - Progressive Web App 之我见 · GDG IO Redux 北京 2016 25 | - [CSS Still Sucks 2015][2] · 2015 26 | - [JavaScript 模块化七日谈][1] · 2015 27 | 28 | 29 | ##### 媒体关注 30 | 31 | - [Hux 黄玄:从全局视角看 React 生态][14] · 直播 · 图灵 8 点半 · 2023 32 | - [2022 中国开源先锋 33 人][18] · SegmentFault · 2023 33 | - [React 黄玄:不懂艺术的 B-Boy 不是 Swag 的程序员][16] · Gitee 封面人物 · 2022 34 | - [在硅谷当程序员是怎样的体验?][17] · 知乎[《我所向往的职业啊》](https://movie.douban.com/subject/36015036/) · 2022 35 | 36 | <!-- 37 | - [掘金 AMA:我是前端娱乐圈的老人 & Facebook 实习生 -- 黄玄][19] · 2018 38 | --> 39 | 40 | 41 | [1]: //huangxuan.me/2015/07/09/js-module-7day/ 42 | [2]: //huangxuan.me/2015/12/28/css-sucks-2015/ 43 | [3]: //huangxuan.me/2016/06/05/pwa-in-my-pov/ 44 | [4]: //huangxuan.me/2016/10/20/pwa-qcon2016/ 45 | [5]: //huangxuan.me/2016/11/20/sw-101-gdgdf/ 46 | [6]: https://yanshuo.io/assets/player/?deck=58ac8598b123db0067292f92 "PWA Rehashing" 47 | [7]: https://yanshuo.io/assets/player/?deck=593ad6fbfe88c2006a0a0d6d "The State of PWA" 48 | [8]: https://yanshuo.io/assets/player/?deck=594d673d570c357d0698a950 "Building PWA" 49 | [9]: //huangxuan.me/jsconfcn2017/ 50 | [10]: https://reactnative.dev/blog/2021/10/26/toward-hermes-being-the-default 51 | [11]: https://youtu.be/lGEMwh32soc 52 | [12]: https://reactjs.org/blog/2022/06/15/react-labs-what-we-have-been-working-on-june-2022.html 53 | [13]: https://www.bilibili.com/video/BV1LY411Q7hC/?spm_id_from=333.999.0.0 54 | [14]: https://appycyfaqcq1951.pc.xiaoe-tech.com/p/t_pc/course_pc_detail/video/v_64477dbfe4b0cf39e6c11d2a 55 | [15]: https://segmentfault.com/a/1190000043208486 56 | [16]: https://gitee.com/gitee-stars/30 57 | [17]: https://www.zhihu.com/zvideo/1542577108190068737?page=ogv 58 | [18]: https://segmentfault.com/a/1190000043208486 59 | [19]: https://juejin.cn/post/6844903750155419655 60 | [20]: https://www.bilibili.com/video/BV1SC4y1c7ju/ 61 | [21]: https://www.bilibili.com/video/BV1uz421d7Ch/ 62 | -------------------------------------------------------------------------------- /_includes/ads.html: -------------------------------------------------------------------------------- 1 | <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> 2 | <!-- first shot --> 3 | <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-6487568398225121" data-ad-slot="4814308751" 4 | data-ad-format="auto" data-full-width-responsive="true"></ins> 5 | <script> 6 | (adsbygoogle = window.adsbygoogle || []).push({}); 7 | </script> 8 | -------------------------------------------------------------------------------- /_includes/featured-tags.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | @param {boolean} bottom - bottom will render <hr> 3 | {% endcomment %} 4 | 5 | {% if site.featured-tags %} 6 | <section> 7 | {% if include.bottom %} 8 | <hr class="hidden-sm hidden-xs"> 9 | {% endif %} 10 | <h5><a href="{{'/archive/' | prepend: site.baseurl }}">FEATURED TAGS</a></h5> 11 | <div class="tags"> 12 | {% capture tags %} 13 | {% comment %} 14 | there must be no space between for and if otherwise this tricky sort won't work. 15 | url_encode/decode is for escaping otherwise extra <a> will get generated 16 | but it will break sort... 17 | {% endcomment %} 18 | {% for tag in site.tags %}{% if tag[1].size > site.featured-condition-size %} 19 | <a data-sort="{{ site.posts.size | minus: tag[1].size | prepend: '0000' | slice: -4, 4 }}" 20 | href="{{ site.baseurl }}/archive/?tag={{ tag[0] | url_encode }}" 21 | title="{{ tag[0] }}" 22 | rel="{{ tag[1].size }}">{{ tag[0] }}</a>__SEPARATOR__ 23 | {% endif %}{% endfor %} 24 | {% endcapture %} 25 | {{ tags | split:'__SEPARATOR__' | sort }} 26 | </div> 27 | </section> 28 | {% endif %} -------------------------------------------------------------------------------- /_includes/friends.html: -------------------------------------------------------------------------------- 1 | {% if site.friends %} 2 | <hr> 3 | <h5>FRIENDS</h5> 4 | <ul class="list-inline"> 5 | {% for friend in site.friends %} 6 | <li><a href="{{friend.href}}">{{friend.title}}</a></li> 7 | {% endfor %} 8 | </ul> 9 | {% endif %} -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | <head> 2 | <meta charset="utf-8"> 3 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> 4 | <meta name="google-site-verification" content="xBT4GhYoi5qRD5tr338pgPM5OWHHIDR6mNg1a3euekI" /> 5 | <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> 6 | <meta name="description" content="{{ site.description }}"> 7 | <meta name="keywords" content="{{ site.keyword }}"> 8 | <meta name="theme-color" content="{{ site.chrome-tab-theme-color }}"> 9 | 10 | <!-- Open Graph --> 11 | <meta property="og:title" 12 | content="{% if page.title %}{{ page.title }} - {{ site.SEOTitle }}{% else %}{{ site.SEOTitle }}{% endif %}"> 13 | {% case page.layout %} 14 | {% when 'post' %} 15 | <meta property="og:type" content="article"> 16 | <meta property="og:description" content="{{ page.excerpt | strip_html | truncate:200 }}"> 17 | {% if page.date %} 18 | <meta property="article:published_time" content="{{ page.date | date: " %Y-%m-%dT%H:%M:%SZ" }}"> 19 | {% endif %} 20 | {% if page.author %} 21 | <meta property="article:author" content="{{ page.author }}"> 22 | {% endif %} 23 | {% for tag in page.tags %} 24 | <meta property="article:tag" content="{{ tag }}"> 25 | {% endfor %} 26 | {% else %} 27 | <meta property="og:type" content="website"> 28 | <meta property="og:description" 29 | content="{% if page.description %}{{ page.description }}{% else %}{{ site.description }}{% endif %}"> 30 | {% endcase %} 31 | <meta property="og:image" content="{{ site.url }}{{ site.sidebar-avatar }}"> 32 | <meta property="og:url" content="{{ site.url }}{{ page.url }}"> 33 | <meta property="og:site_name" content="{{ site.SEOTitle }}"> 34 | 35 | <title>{% if page.title %}{{ page.title }} - {{ site.SEOTitle }}{% else %}{{ site.SEOTitle }}{% endif %}</title> 36 | 37 | <!-- Web App Manifest --> 38 | <link rel="manifest" href="{{ site.baseurl }}/pwa/manifest.json"> 39 | 40 | <!-- Favicon --> 41 | <link rel="shortcut icon" href="{{ site.baseurl }}/img/favicon.ico"> 42 | 43 | <!-- Canonical URL --> 44 | <link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}"> 45 | 46 | <!-- Bootstrap Core CSS --> 47 | <link rel="stylesheet" href="{{ " /css/bootstrap.min.css" | prepend: site.baseurl }}"> 48 | 49 | <!-- Custom CSS --> 50 | <link rel="stylesheet" href="{{ " /css/hux-blog.min.css" | prepend: site.baseurl }}"> 51 | 52 | <!-- Custom Fonts --> 53 | <!-- <link href="http://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css"> --> 54 | <!-- Hux change font-awesome CDN to qiniu --> 55 | <link href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" 56 | type="text/css"> 57 | 58 | 59 | <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> 60 | <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> 61 | <!--[if lt IE 9]> 62 | <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> 63 | <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> 64 | <![endif]--> 65 | 66 | <!-- ga & ba script hoook --> 67 | <script></script> 68 | 69 | <!-- Google AdSense --> 70 | <script data-ad-client="ca-pub-6487568398225121" async 71 | src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> 72 | </head> 73 | -------------------------------------------------------------------------------- /_includes/intro-header.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | @param {string} type - 'page' | 'post' | 'keynote' 3 | @param {boolean} short 4 | {% endcomment %} 5 | 6 | {% if include.type == 'post' or include.type == 'page' %} 7 | <style type="text/css"> 8 | header.intro-header{ 9 | position: relative; 10 | background-image: url('{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %}'); 11 | background: {{ page.header-bg-css }}; 12 | } 13 | 14 | {% if page.header-mask %} 15 | header.intro-header .header-mask{ 16 | width: 100%; 17 | height: 100%; 18 | position: absolute; 19 | background: rgba(0,0,0, {{ page.header-mask }}); 20 | } 21 | {% endif %} 22 | </style> 23 | {% endif %} 24 | 25 | {% if include.type == 'post' %} 26 | {% if page.header-style == 'text' %} 27 | <header class="intro-header style-text" > 28 | {% else %} 29 | <header class="intro-header" > 30 | {% endif %} 31 | <div class="header-mask"></div> 32 | {% if page.header-img-credit %} 33 | <div class="header-img-credit"> 34 | Image by <a href="//{{page.header-img-credit-href}}">{{page.header-img-credit}}</a> 35 | </div> 36 | {% endif %} 37 | <div class="container"> 38 | <div class="row"> 39 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"> 40 | <div class="post-heading"> 41 | <div class="tags"> 42 | {% for tag in page.tags %} 43 | <a class="tag" href="{{ site.baseurl }}/archive/?tag={{ tag | url_encode }}" title="{{ tag }}">{{ tag }}</a> 44 | {% endfor %} 45 | </div> 46 | <h1>{{ page.title }}</h1> 47 | {% comment %} always create a h2 for keeping the margin {% endcomment %} 48 | <h2 class="subheading">{{ page.subtitle }}</h2> 49 | <span class="meta">Posted by {% if page.author %}{{ page.author }}{% else %}{{ site.title }}{% endif %} on {{ page.date | date: "%B %-d, %Y" }}</span> 50 | </div> 51 | </div> 52 | </div> 53 | </div> 54 | </header> 55 | {% endif %} 56 | 57 | {% if include.type == 'keynote' %} 58 | <style type="text/css"> 59 | header.intro-header{ 60 | height: 500px; 61 | overflow: hidden; 62 | } 63 | header.intro-header .container{ 64 | visibility: hidden; 65 | } 66 | header iframe{ 67 | width: 100%; 68 | height: 100%; 69 | border: 0; 70 | } 71 | </style> 72 | <header class="intro-header" > 73 | <iframe src="{{page.iframe}}"></iframe> 74 | <!-- keep for SEO --> 75 | <div class="container"> 76 | <div class="row"> 77 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"> 78 | <div class="post-heading"> 79 | <div class="tags"> 80 | {% for tag in page.tags %} 81 | <a class="tag" href="{{ site.baseurl }}/archive/?tag={{ tag | url_encode }}" title="{{ tag }}">{{ tag }}</a> 82 | {% endfor %} 83 | </div> 84 | <h1>{{ page.title }}</h1> 85 | {% comment %} always create a h2 for keeping the margin {% endcomment %} 86 | <h2 class="subheading">{{ page.subtitle }}</h2> 87 | <span class="meta">Posted by {% if page.author %}{{ page.author }}{% else %}{{ site.title }}{% endif %} 88 | on {{ page.date | date: "%B %-d, %Y" }}</span> 89 | </div> 90 | </div> 91 | </div> 92 | </div> 93 | </header> 94 | {% endif %} 95 | 96 | {% if include.type == 'page' %} 97 | <header class="intro-header" style="background-image: url('{{ site.baseurl }}/{% if page.header-img %}{{ page.header-img }}{% else %}{{ site.header-img }}{% endif %}')"> 98 | <div class="header-mask"></div> 99 | <div class="container"> 100 | <div class="row"> 101 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"> 102 | {% if include.short %} 103 | <div class="site-heading" id="tag-heading"> 104 | {% else %} 105 | <div class="site-heading"> 106 | {% endif %} 107 | <h1>{% if page.title %}{{ page.title }}{% else %}{{ site.title }}{% endif %}</h1> 108 | <span class="subheading">{{ page.description }}</span> 109 | </div> 110 | </div> 111 | </div> 112 | </div> 113 | </header> 114 | {% endif %} 115 | -------------------------------------------------------------------------------- /_includes/mathjax_support.html: -------------------------------------------------------------------------------- 1 | <script type="text/x-mathjax-config"> 2 | MathJax.Hub.Config({ 3 | TeX: { 4 | equationNumbers: { 5 | autoNumber: "AMS" 6 | } 7 | }, 8 | SVG: { 9 | scale: 90 10 | }, 11 | tex2jax: { 12 | inlineMath: [ ['#39;,'#39;] ], 13 | displayMath: [ ['$','$'] ], 14 | processEscapes: true, 15 | } 16 | }); 17 | </script> 18 | <script type="text/javascript" 19 | src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG"> 20 | </script> -------------------------------------------------------------------------------- /_includes/multilingual-sel.html: -------------------------------------------------------------------------------- 1 | <!-- Language Selector --> 2 | <select class="sel-lang" onchange= "onLanChange(this.options[this.options.selectedIndex].value)"> 3 | <option value="0" selected> 中文 | Chinese </option> 4 | <option value="1"> 英文 | English </option> 5 | </select> 6 | 7 | -------------------------------------------------------------------------------- /_includes/nav.html: -------------------------------------------------------------------------------- 1 | <!-- Navigation --> 2 | {% if page.nav-style == "invert" or page.header-style == "text" %} 3 | <nav class="navbar navbar-default navbar-custom navbar-fixed-top invert"> 4 | {% else %} 5 | <nav class="navbar navbar-default navbar-custom navbar-fixed-top"> 6 | {% endif %} 7 | <div class="container-fluid"> 8 | <!-- Brand and toggle get grouped for better mobile display --> 9 | <div class="navbar-header page-scroll"> 10 | <button type="button" class="navbar-toggle"> 11 | <span class="sr-only">Toggle navigation</span> 12 | <span class="icon-bar"></span> 13 | <span class="icon-bar"></span> 14 | <span class="icon-bar"></span> 15 | </button> 16 | <a class="navbar-brand" href="{{ site.baseurl }}/">{{ site.title }}</a> 17 | </div> 18 | 19 | <!-- Collect the nav links, forms, and other content for toggling --> 20 | <div id="huxblog_navbar"> 21 | <div class="navbar-collapse"> 22 | <ul class="nav navbar-nav navbar-right"> 23 | <li> 24 | <a href="{{ site.baseurl }}/">Home</a> 25 | </li> 26 | {% for page in site.pages %} 27 | {% if page.title and page.hide-in-nav != true %} 28 | <li> 29 | <a href="{{ page.url | prepend: site.baseurl }}">{{ page.title }}</a> 30 | </li> 31 | {% endif %} 32 | {% endfor %} 33 | <li class="search-icon"> 34 | <a href="javascript:void(0)"> 35 | <i class="fa fa-search"></i> 36 | </a> 37 | </li> 38 | </ul> 39 | </div> 40 | </div> 41 | <!-- /.navbar-collapse --> 42 | </div> 43 | <!-- /.container --> 44 | </nav> 45 | 46 | <script> 47 | // Drop Bootstarp low-performance Navbar 48 | // Use customize navbar with high-quality material design animation 49 | // in high-perf jank-free CSS3 implementation 50 | var $body = document.body; 51 | var $toggle = document.querySelector('.navbar-toggle'); 52 | var $navbar = document.querySelector('#huxblog_navbar'); 53 | var $collapse = document.querySelector('.navbar-collapse'); 54 | 55 | var __HuxNav__ = { 56 | close: function () { 57 | $navbar.className = " "; 58 | // wait until animation end. 59 | setTimeout(function () { 60 | // prevent frequently toggle 61 | if ($navbar.className.indexOf('in') < 0) { 62 | $collapse.style.height = "0px" 63 | } 64 | }, 400) 65 | }, 66 | open: function () { 67 | $collapse.style.height = "auto" 68 | $navbar.className += " in"; 69 | } 70 | } 71 | 72 | // Bind Event 73 | $toggle.addEventListener('click', function (e) { 74 | if ($navbar.className.indexOf('in') > 0) { 75 | __HuxNav__.close() 76 | } else { 77 | __HuxNav__.open() 78 | } 79 | }) 80 | 81 | /** 82 | * Since Fastclick is used to delegate 'touchstart' globally 83 | * to hack 300ms delay in iOS by performing a fake 'click', 84 | * Using 'e.stopPropagation' to stop 'touchstart' event from 85 | * $toggle/$collapse will break global delegation. 86 | * 87 | * Instead, we use a 'e.target' filter to prevent handler 88 | * added to document close HuxNav. 89 | * 90 | * Also, we use 'click' instead of 'touchstart' as compromise 91 | */ 92 | document.addEventListener('click', function (e) { 93 | if (e.target == $toggle) return; 94 | if (e.target.className == 'icon-bar') return; 95 | __HuxNav__.close(); 96 | }) 97 | </script> -------------------------------------------------------------------------------- /_includes/search.html: -------------------------------------------------------------------------------- 1 | <!-- Search --> 2 | <div class="search-page"> 3 | <div class="search-icon-close-container"> 4 | <span class="search-icon-close"> 5 | <i class="fa fa-chevron-down"></i> 6 | </span> 7 | </div> 8 | <div class="search-main container"> 9 | <div class="row"> 10 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"> 11 | <form></form> 12 | <input type="text" id="search-input" placeholder="$ grep..."> 13 | </form> 14 | <div id="search-results" class="mini-post-list"></div> 15 | </div> 16 | </div> 17 | </div> 18 | </div> -------------------------------------------------------------------------------- /_includes/short-about.html: -------------------------------------------------------------------------------- 1 | <section class="visible-md visible-lg"> 2 | <hr> 3 | <h5><a href="{{'/about/' | prepend: site.baseurl }}">ABOUT ME</a></h5> 4 | <div class="short-about"> 5 | {% if site.sidebar-avatar %} 6 | <img src="{{site.sidebar-avatar}}" /> 7 | {% endif %} 8 | {% if site.sidebar-about-description %} 9 | <p>{{site.sidebar-about-description}}</p> 10 | {% endif %} 11 | <!-- SNS Link --> 12 | {% include sns-links.html %} 13 | </div> 14 | </section> -------------------------------------------------------------------------------- /_includes/sns-links.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | @param {Boolean} center 3 | {% endcomment %} 4 | 5 | {% if include.center %} 6 | <ul class="list-inline text-center"> 7 | {% else %} 8 | <ul class="list-inline"> 9 | {% endif %} 10 | 11 | {% if site.RSS %} 12 | <li> 13 | <a href="{{ "/feed.xml" | prepend: site.baseurl }}"> 14 | <span class="fa-stack fa-lg"> 15 | <i class="fa fa-circle fa-stack-2x"></i> 16 | <i class="fa fa-rss fa-stack-1x fa-inverse"></i> 17 | </span> 18 | </a> 19 | </li> 20 | {% endif %} 21 | {% if site.twitter_username %} 22 | <li> 23 | <a href="https://twitter.com/{{ site.twitter_username }}"> 24 | <span class="fa-stack fa-lg"> 25 | <i class="fa fa-circle fa-stack-2x"></i> 26 | <i class="fa fa-twitter fa-stack-1x fa-inverse"></i> 27 | </span> 28 | </a> 29 | </li> 30 | {% endif %} 31 | {% if site.zhihu_username %} 32 | <li> 33 | <a target="_blank" href="https://www.zhihu.com/people/{{ site.zhihu_username }}"> 34 | <span class="fa-stack fa-lg"> 35 | <i class="fa fa-circle fa-stack-2x"></i> 36 | <i class="fa fa-stack-1x fa-inverse">知</i> 37 | </span> 38 | </a> 39 | </li> 40 | {% endif %} 41 | {% if site.weibo_username %} 42 | <li> 43 | <a target="_blank" href="http://weibo.com/{{ site.weibo_username }}"> 44 | <span class="fa-stack fa-lg"> 45 | <i class="fa fa-circle fa-stack-2x"></i> 46 | <i class="fa fa-weibo fa-stack-1x fa-inverse"></i> 47 | </span> 48 | </a> 49 | </li> 50 | {% endif %} 51 | {% if site.facebook_username %} 52 | <li> 53 | <a target="_blank" href="https://www.facebook.com/{{ site.facebook_username }}"> 54 | <span class="fa-stack fa-lg"> 55 | <i class="fa fa-circle fa-stack-2x"></i> 56 | <i class="fa fa-facebook fa-stack-1x fa-inverse"></i> 57 | </span> 58 | </a> 59 | </li> 60 | {% endif %} 61 | {% if site.github_username %} 62 | <li> 63 | <a target="_blank" href="https://github.com/{{ site.github_username }}"> 64 | <span class="fa-stack fa-lg"> 65 | <i class="fa fa-circle fa-stack-2x"></i> 66 | <i class="fa fa-github fa-stack-1x fa-inverse"></i> 67 | </span> 68 | </a> 69 | </li> 70 | {% endif %} 71 | {% if site.linkedin_username %} 72 | <li> 73 | <a target="_blank" href="https://www.linkedin.com/in/{{ site.linkedin_username }}"> 74 | <span class="fa-stack fa-lg"> 75 | <i class="fa fa-circle fa-stack-2x"></i> 76 | <i class="fa fa-linkedin fa-stack-1x fa-inverse"></i> 77 | </span> 78 | </a> 79 | </li> 80 | {% endif %} 81 | </ul> -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | <!DOCTYPE html> 2 | <html lang="en"> 3 | 4 | {% include head.html %} 5 | 6 | <!-- hack iOS CSS :active style --> 7 | <body ontouchstart=""> 8 | 9 | {% include nav.html %} 10 | {% include search.html %} 11 | 12 | {{ content }} 13 | 14 | {% include footer.html %} 15 | 16 | 17 | <!-- Image to hack wechat --> 18 | <img src="/img/icon_wechat.png" width="0" height="0" /> 19 | <!-- Migrate from head to bottom, no longer block render and still work --> 20 | 21 | </body> 22 | 23 | </html> 24 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | <!-- Page Header --> 6 | {% include intro-header.html type='page' %} 7 | 8 | <!-- Main Content --> 9 | <div class="container"> 10 | <div class="row"> 11 | {% if site.sidebar == false %} 12 | <!-- NO SIDEBAR --> 13 | <!-- PostList Container --> 14 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 15 | postlist-container"> 16 | {{ content }} 17 | </div> 18 | <!-- Sidebar Container --> 19 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1 20 | sidebar-container"> 21 | <!-- Featured Tags --> 22 | {% include featured-tags.html %} 23 | 24 | <!-- Friends Blog --> 25 | {% include friends.html %} 26 | </div> 27 | {% else %} 28 | 29 | <!-- USE SIDEBAR --> 30 | <!-- PostList Container --> 31 | <div class="col-lg-8 col-lg-offset-1 col-md-8 col-md-offset-1 col-sm-12 32 | col-xs-12 postlist-container"> 33 | {{ content }} 34 | </div> 35 | <!-- Sidebar Container --> 36 | <div class="col-lg-3 col-lg-offset-0 col-md-3 col-md-offset-0 col-sm-12 37 | col-xs-12 sidebar-container"> 38 | <!-- Featured Tags --> 39 | {% include featured-tags.html %} 40 | 41 | <!-- Short About --> 42 | {% include short-about.html %} 43 | 44 | <!-- Friends Blog --> 45 | {% include friends.html %} 46 | 47 | <!-- Ads --> 48 | {% include ads.html %} 49 | </div> 50 | {% endif %} 51 | </div> 52 | </div> 53 | 54 | {% if site.page-mathjax %} 55 | <!-- Add support for Mathjax by Voleking--> 56 | <!-- If you want to see formulars well in post preview, Maybe you should add this.--> 57 | <!-- However, most of the time formulars may not appear in the post preview, you can delete it.--> 58 | <script type="text/x-mathjax-config"> 59 | MathJax.Hub.Config({ 60 | TeX: { 61 | equationNumbers: { 62 | autoNumber: "AMS" 63 | } 64 | }, 65 | tex2jax: { 66 | inlineMath: [ ['#39;,'#39;] ], 67 | displayMath: [ ['$','$'] ], 68 | processEscapes: true, 69 | } 70 | }); 71 | </script> 72 | <script type="text/javascript" 73 | src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> 74 | {% endif %} 75 | -------------------------------------------------------------------------------- /_posts/2014-01-29-hello-2015.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Hello 2015" 4 | subtitle: " \"Hello World, Hello Blog\"" 5 | date: 2015-01-29 12:00:00 6 | author: "Hux" 7 | header-img: "img/post-bg-2015.jpg" 8 | catalog: true 9 | tags: 10 | - Meta 11 | --- 12 | 13 | > “Yeah It's on. ” 14 | 15 | 16 | Hux 的 Blog 就这么开通了。 17 | 18 | [跳过废话,直接看技术实现 ](#build) 19 | 20 | 2015 年,Hux 总算有个地方可以好好写点东西了。 21 | 22 | 23 | 作为一个程序员, Blog 这种轮子要是挂在大众博客程序上就太没意思了。一是觉得大部分 Blog 服务都太丑,二是觉得不能随便定制不好玩。之前因为太懒没有折腾,结果就一直连个写 Blog 的地儿都没有。 24 | 25 | 在玩了一段时间知乎之后,答题的快感又激起了我开博客的冲动。之前的[个人网站](http://huangxuan.me/portfolio)是作品集形式的(现在集成进来了),并不适合用来写博文,一不做二不休,花一天搞一个吧! 26 | 27 | 28 | <p id = "build"></p> 29 | 30 | ## 正文 31 | 32 | 接下来说说搭建这个博客的技术细节。 33 | 34 | 正好之前就有关注过 [GitHub Pages](https://pages.github.com/) + [Jekyll](http://jekyllrb.com/) 快速 Building Blog 的技术方案,非常轻松时尚。 35 | 36 | 其优点非常明显: 37 | 38 | * **Markdown** 带来的优雅写作体验 39 | * 非常熟悉的 Git workflow ,**Git Commit 即 Blog Post** 40 | * 利用 GitHub Pages 的域名和免费无限空间,不用自己折腾主机 41 | * 如果需要自定义域名,也只需要简单改改 DNS 加个 CNAME 就好了 42 | * Jekyll 的自定制非常容易,基本就是个模版引擎 43 | 44 | 45 | 本来觉得最大的缺点可能是 GitHub 在国内访问起来太慢,所以第二天一起床就到 GitCafe(Chinese GitHub Copy,现在被 Coding 收购了) 迁移了一个[镜像](http://huxpro.coding.me)出来,结果还是巨慢。 46 | 47 | 哥哥可是个前端好嘛! 果断开 Chrome DevTool 查了下网络请求,原来是 **pending 在了 Google Fonts** 上,页面渲染一直被阻塞到请求超时为止,难怪这么慢。 48 | 忍痛割爱,只好把 Web Fonts 去了(反正超时看到的也只能是 fallback ),果然一下就正常了,而且 GitHub 和 GitCafe 对比并没有感受到明显的速度差异,虽然 github 的 ping 值明显要高一些,达到了 300ms,于是用 DNSPOD 优化了一下速度。 49 | 50 | 51 | --- 52 | 53 | 配置的过程中也没遇到什么坑,基本就是 Git 的流程,相当顺手 54 | 55 | 大的 Jekyll 主题上直接 fork 了 Clean Blog(这个主题也相当有名,就不多赘述了。唯一的缺点大概就是没有标签支持,于是我给它补上了。) 56 | 57 | 本地调试环境需要 `gem install jekyll`,结果 rubygem 的源居然被墙了……后来手动改成了我大淘宝的镜像源才成功 58 | 59 | Theme 的 CSS 是基于 Bootstrap 定制的,看得不爽的地方直接在 Less 里改就好了(平时更习惯 SCSS 些),**不过其实我一直觉得 Bootstrap 在移动端的体验做得相当一般,比我在淘宝参与的团队 CSS 框架差多了……**所以为了体验,也补了不少 CSS 进去 60 | 61 | 最后就进入了耗时反而最长的**做图、写字**阶段,也算是进入了**写博客**的正轨,因为是类似 Hack Day 的方式去搭这个站的,所以折腾折腾着大半夜就过去了。 62 | 63 | 第二天考虑中文字体的渲染,fork 了 [Type is Beautiful](http://www.typeisbeautiful.com/) 的 `font` CSS,调整了字号,适配了 Win 的渣渲染,中英文混排效果好多了。 64 | 65 | 66 | ## 后记 67 | 68 | 回顾这个博客的诞生,纯粹是出于个人兴趣。在知乎相关问题上回答并获得一定的 star 后,我决定把这个博客主题当作一个小小的开源项目来维护。 69 | 70 | 在经历 v1.0 - v1.5 的蜕变后,这个博客主题愈发完整,不但增加了诸多 UI 层的优化(opinionated);在代码层面,更加丰富的配置项也使得这个主题拥有了更好的灵活性与可拓展性。而作为一个开源项目,我也积极的为其完善文档与解决 issue。 71 | 72 | 如果你恰好逛到了这里,希望你也能喜欢这个博客主题。 73 | 74 | —— Hux 后记于 2015.10 75 | -------------------------------------------------------------------------------- /_posts/2014-08-16-miui6.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "如何评价 MIUI 6?" 4 | date: 2014-08-16 12:00:00 5 | author: "Hux" 6 | header-img: "img/post-bg-miui6.jpg" 7 | tags: 8 | - 知乎 9 | - 产品 10 | - UX/UI 11 | --- 12 | 13 | > 这篇文章转载自[我在知乎上的回答](http://www.zhihu.com/question/24783844/answer/29286896) 14 | 15 | 16 | <div> 17 | <blockquote>MIUI 6,充满了“借鉴”,iOS 7 版的 Android…… 18 | <br>米 4,碉堡了,不服跑个分,简直就是 iPhone 4……</blockquote>你们说得这些我一点都不反对。 19 | <br> 20 | <br><b>可是,你们对小米的要求太高了</b>。 21 | <br> 22 | <br>其实小米说到底也不过是一个才初创4年的公司而已, 23 | <br><b>你是指望小米能引领一套新的设计风格?</b> 24 | <br><b>还是指望它能在国际上体现一下我国的自主创新能力?</b> 25 | <br> 26 | <br>你想太多了。 27 | <br> 28 | <br>更何况,<b>MIUI也不是没有设计</b>,它比很多国内,国际大厂的ROM好看好用太多了。 29 | <br>它只是没有多少新设计而已, iOS 7 的视觉,混着大部分 Android + WP 的交互。也不知道是因为确实欣赏 Android 的一些交互,还是因为毕竟是基于 Android 懒得改了。 30 | <br> 31 | <br><b>因为没有一个背后的设计思想在支撑,于是它就把所有自己觉得好,觉得会被认可的东西抄过来了而已。</b> 32 | <br> 33 | <br><b>这思路一点问题都没有,</b><b>大部分用户一定会觉得更好看了</b>,国际范儿又有设计感。最多是少数圈内人士(包括我),那群也不真正买它手机用的人,在那愤愤不平而已。 34 | <br> 35 | <br><b>自立门派风险太大了。</b> 36 | <br><b>MI 4 的配置 + MIUI 6,在这个价位几乎是无敌的,这就够了。</b> 37 | <br> 38 | <br>至于官方说的什么“糖果式”设计,那简直就是笑话。跟 Ive 的 iOS 7 或是 Material Design,Metro 所设计之设计,完全不在一个高度上。 39 | <br> 40 | <br> 41 | <br>其实有的时候觉得小米很像腾讯(尤其是更早些年的腾讯)。 42 | <br><b>其实本来也就不是什么创新者的角色,那就做借鉴和整合呗。</b> 43 | <br> 44 | <br>用户喜欢什么, 45 | <br>公司需要什么, 46 | <br>大众流行什么, 47 | <br>那我们就做呗。 48 | <br> 49 | <br><b>拿下市场才是第一位的,不出错才是第一位的</b>。 50 | <br><b>先做大了才有可能去做更大的事啊</b>。 51 | <br> 52 | <br>老罗再有情怀,锤子要是死了,那也就这么死了。 53 | <br> 54 | <br>你指责小米没有多少创新,或是腾讯老是山寨 start up ,我同意,我陪你愤愤不平,可是又有什么意思呢。 55 | <br> 56 | <br>它们这么做,对现有公司发展来说, 57 | <br><b>简直是一点错都没有。</b> 58 | <br> 59 | <br> 60 | </div> 61 | -------------------------------------------------------------------------------- /_posts/2014-09-04-is-pure-android-better.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "对中国用户而言,Pure Android 是否比 MIUI 或 Flyme 体验更好?" 4 | subtitle: "" 5 | date: 2014-09-04 12:00:00 6 | author: "Hux" 7 | header-img: "img/post-bg-android.jpg" 8 | tags: 9 | - 知乎 10 | - 产品 11 | - UX/UI 12 | --- 13 | 14 | > 这篇文章转载自[我在知乎上的回答](http://www.zhihu.com/question/25104721/answer/30108886) 15 | 16 | 17 | <p>哎呀~不要站队嘛。其实这是一个很有意思的题目,让我们一点点来看 18 | <br> 19 | <br>哦对,谢妖~。本人是Nexus 5用户,系统当然是Pure Android KitKat啦(臭谷粉!点Down!喂喂喂我还没给结论呢) 20 | <br><b>毕竟是回答问题嘛,先给一个明确的答案</b>: 21 | <br> 22 | <br><b>否。(</b><b>对中国用户而言,Pure Android 并不比 MIUI 或 Flyme 体验更好。</b><b>)</b> 23 | 24 | <p>从下面「 居然比关注数还多」的回答中,就可以看出大家都是急于站队的样子:</p> 25 | 26 | <ul> 27 | <li>Google Service!翻墙很轻松好吗!Geek站过来,有品味绝逼原生阿。</li> 28 | <li>没用过Pure,国内Google能用!?本地化多重要,易用果断MIUI/Flyme 啊!(咦 米粉和魅粉居然在一致对外上达成了共识)</li> 29 | </ul> 30 | <br>从答案我们也可以看出,中国用户的确是一个过于复杂的群体,那这个问题怎么办? 31 | <br> 32 | <br><b>数学老师教过哒,分类讨论啊!</b> 33 | <br>(来,开始认真了。注意,我只分两类,数量非常小的Geek用户,和其余都算在内的非Geek用户) 34 | <br> 35 | <br> 36 | 37 | <p>先说好理解的:</p> 38 | 39 | <ul> 40 | <li><b>为什么 Geek 用户 都爱使用Pure Android?:</b> 41 | </li> 42 | </ul>在国内,使用Pure Android其实是有很多障碍的:众所周知Google基本被墙死,去年还能上上的G+,Gmail 最近基本报废,回国后Google Now不开VPN永远都是Sign error或者No internet connection……那干嘛还用? 43 | <br> 44 | <br><b>因为这群人是Geek呀!</b>这群谷粉、安卓粉、IT科技粉、设计师、工程师们,这群充满技术情节的人儿们,为了我们的品味(逼格),挂着VPN,连着美版的Play Store,用着Android/Material Design 的 GMS,Chrome Beta,FB,Twitter,WhatsApp……就这么一路高歌的走下去了。 45 | <br> 46 | <br>你看!Action Bar + Navigation Drawer 多好用! 47 | <br>你看!Fixed Tabs 可以滑的好吗! 48 | <br>你看!流畅不!ART开起来妥妥的流畅度爆iOS! 49 | <br>你看!原生Android 哪里会越用用卡!?你升4.4.4了吗 ? 50 | <br> 51 | <br><b>哪里要担心这群人啊。</b>国内买不到的Nexus,用不了GMS,这都不叫事。 52 | <br> 53 | <br> 54 | 55 | <p>那么,</p> 56 | 57 | <ul> 58 | <li><b>为什么 非Geek 用户 不适合使用Pure Android?:</b> 59 | </li> 60 | </ul>GMS的问题就不多说了,妥妥是用不了,在VPN之间切换也是麻烦。 61 | <br>也不说Pure Android不那么好刷到的问题(当然你可以刷CM), 62 | <br>我们就直接来看最核心的问题: 63 | <br> 64 | <br><b>「 Pure Android 的交互设计真的比 MIUI / Flyme 好吗?」<br></b> 65 | <br><b>不见得。</b> 66 | <br><b>所谓设计,第一个要考虑的就是目标用户。</b> 67 | <br> 68 | <br>为什么Pure Android的交互设计让Geek觉得用户体验好? 69 | <br> 70 | <ul> 71 | <li>国外规范的 Android Design 生态环境打造统一的 Pure Android 体验</li> 72 | <li>更高级的手势/App运用带来了很多便利(典型的例子SwipePad)</li> 73 | <li>有着工程师思想的他们可以轻易理解Android的复杂逻辑</li> 74 | <li>有着工程师思想的他们总能自己轻松躲开一些设计问题</li> 75 | </ul> 76 | <br>而 Pure Android 之于 普通用户 呢? 77 | <br><b>「 这些优势基本荡然无存」</b>,反而,混乱的国内生态环境带来大部分中国用户对Android Design的陌生,相比iOS复杂许多的Android逻辑带来较高的学习成本…… 78 | <br> 79 | <br>而MIUI/Flyme在设计方面上的本地化,主要就是出来解决这个问题的。 80 | <br>我们可以看到,其实MIUI/Flyme做得大部分工作,除了视觉外,就是<b>简化信息层级,降低交互学习成本,遮住Android系统过于复杂的部分,在易用性上向iOS靠拢</b>。 81 | <br> 82 | <br>如果说在这里MIUI/Flyme还只能和Pure Android 打个平手的话…… 83 | <br> 84 | <br><b>MIUI 和 Flyme 的本地化还远没有完:</b> 85 | <br> 86 | <br>你在国内总要用国内的互联网服务吧? 87 | <br><b>集成,</b>我全给你全整合进来,打造一条龙服务 88 | <br> 89 | <ul> 90 | <li>应用商店 91 | <br> 92 | </li> 93 | <li>云存储/云服务(自己提供或合作) 94 | <br> 95 | </li> 96 | <li>数字娱乐消费(音乐/游戏/阅读/视频/主题/壁纸/铃声……) 97 | <br> 98 | </li> 99 | <li>安全(小白最爱用的系统清理,陌生号码拦截……) 100 | <br> 101 | </li> 102 | <li>生活服务(支付,地图,快递,订餐,打车,旅游……) 103 | <br> 104 | </li> 105 | <li>社交(美图,快速分享……) 106 | <br> 107 | </li> 108 | <li>太多了。总之就是你想要什么有什么,自己没有就跟大家合作呗。 109 | <br> 110 | </li> 111 | </ul><b>不够酷?</b>对大部分用户来说够酷了 112 | <br> 113 | <ul> 114 | <li>小米,平板,盒子,电视,路由……MIUI的多屏体验</li> 115 | <li>魅族,联合智能硬件,手表飞机插座……Connect to Meizu</li> 116 | </ul><b>渠道成本低(不是指价格)</b>。这个其实也相当重要 117 | <br> 118 | <ul> 119 | <li>容易刷到,适配机子广,稳定。</li> 120 | <li>国内买得到,线下甚至有体验店,可以教你用呀什么的。</li> 121 | </ul> 122 | <br>更何况,对于大部分非Geek用户,手机虽不再只是当年的通讯工具那么简单,但充其量也就是一个智能电子设备而已。<b>能方便快速的享受到国内主流的互联网应用与服务,完成日常的需求就足以</b>。 123 | <br> 124 | <br><b>MIUI/Flyme 在这方面上的成绩,是Pure Android远不能比的。</b> 125 | <br> 126 | <br>所以我的结论是: 127 | <br> 128 | <br><b>对中国用户而言,Pure Android 并不比 MIUI 或 Flyme 体验更好。</b> 129 | <br><b>对大部分中国用户而言,MIUI 或 Flyme 比 </b><b>Pure Android 的</b><b>体验更好。</b> 130 | <br> 131 | <br> 132 | <br> 133 | <br> 134 | <br>没啥利益相关,我又不是云OS的 135 | </p> 136 | -------------------------------------------------------------------------------- /_posts/2014-10-01-why-alibaba-ux-sucks.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "为什么阿里系软件体验都不好?" 4 | subtitle: "或许这就是所谓的企业 DNA " 5 | date: 2014-10-1 12:00:00 6 | author: "Hux" 7 | header-img: "img/post-bg-alibaba.jpg" 8 | tags: 9 | - 知乎 10 | - 产品 11 | - 阿里 12 | --- 13 | 14 | > 这篇文章转载自[我在知乎上的回答](http://www.zhihu.com/question/25657351/answer/31278511) 15 | 16 | 17 | <div > 18 | <br> 19 | <br><b>一言以蔽之,优先级。</b> 20 | <br>这个优先级并不是由谁或者哪个Boss定的,而是<b>长期的市场竞争和业务需求下的结果</b> 21 | <br> 22 | <br> 23 | <ul> 24 | <li><b>为什么企鹅家的App用户体验较好?</b> 25 | </li> 26 | </ul> 27 | 企鹅家的主力产品,QQ、微信、QQ音乐、QQ空间 等,多是IM(即时通讯)、SNS(社交网络)、数字娱乐 等形态的产品。 28 | <br> 29 | <br><b>这类产品往往必须「直接依靠优秀的产品服务与用户体验」来赢得用户。</b> 30 | <br> 31 | <br>如果这点做不好,产品就无法在竞争中脱颖而出。这也使得在企鹅内部,<b>围绕这部分的要求,需求,反馈 </b><b>都一定最多,使得企鹅不得不把这部分做好</b>。 32 | <br> 33 | <br> 34 | <ul> 35 | <li><b>那为什么阿里系的App用户体验较差?</b> 36 | </li> 37 | </ul> 38 | 阿里系的主力产品,从1688、淘宝、再到支付宝、天猫、淘宝旅行、淘点点、一淘、旺旺,要么是电商类产品,要么就是电商类的延伸产品。 39 | <br> 40 | <br>而这类产品的核心竞争力(或者说要做好的难处),往往在<b>「如何与实体经济,甚至政府 打交道」、</b><b>「如何做好运营」,</b>而非优秀的用户体验。 41 | <br> 42 | <br>应该说,阿里从来都不是不重视用户体验,这两年更是愈发重视。但是因为身处这样的市场环境,<b>阿里必须先完成这些优先级更高的需求(海量的业务,运营需求)以抢占市场,</b> 43 | <br>这才导致阿里内部无法有太多精力focus到客户端体验上。 44 | <br> 45 | <br> 46 | <br> 47 | <br>上面就算基本回答了题主的问题, 48 | <br>不过,知乎惯例,多说几句: 49 | <br> 50 | <br><b>其实,上面的答案,也可以说这都是说辞。</b> 51 | <br> 52 | <br>在我刚刚加入阿里的时候,我也一度纳闷甚至郁闷这个事。直到我开始接触更多的项目,我才能逐渐理解「为什么会这样」。 53 | <br> 54 | <br><b>但是,这并不足以成为借口。</b> 55 | <br><b>该不该改? 当然该改。</b> 56 | <br> 57 | <br>我相信几乎所有阿里人,尤其UED,肯定都不希望这样。 58 | <br>只能说,这需要阿里投入更多的人、更多的时间、更多的努力来做好 59 | <br> 60 | <br> 61 | <br> 62 | <br>以上。 63 | <br> 64 | <br>利益相关: 65 | <br>阿里员工 66 | <br> 67 | <br> 68 | </div> 69 | -------------------------------------------------------------------------------- /_posts/2014-12-13-wechat-block-kuaidi.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "如何看待微信屏蔽快的打车事件?" 4 | subtitle: "恰有小感。" 5 | date: 2014-12-13 6 | author: "Hux" 7 | header-img: "img/post-bg-kuaidi.jpg" 8 | tags: 9 | - 知乎 10 | - 产品 11 | --- 12 | 13 | > 这篇文章转载自[我在知乎上的回答](http://www.zhihu.com/question/26774049/answer/35041458) 14 | 15 | 16 | <div> 17 | 唉。今天恰巧有感,过来小聊几句。 18 | <br>还是要先声明下:<b>所有言论出自个人,与阿里和我所在的团队无关。</b> 19 | <br> 20 | <br> 21 | <br>正文。 22 | <br> 23 | <br>应该很多互联网公司都有这项 “福利” ——<b> 加班到X点以后,报销打车费</b>。 24 | <br>阿里大约是晚上9点。 25 | <br> 26 | <br>初进阿里时还不习惯,想着6点下班后,吃个免费晚饭,赶快坐地铁回家。 27 | <br>后来一是发现高峰期的地铁简直要命,二是确实有太多需求做不完, 平常经常会说: “这个我们晚上再谈…” 28 | <br> 29 | <br>所以晚上加班就成了公司里很多人的常态 ,就算今天 8 点多就已经工作得差不多了,也会习惯性得等到 9 点左右,<b>叫个车回家</b>。 30 | <br> 31 | <br>于是,每天 9 ~ 12 点间,公司里的叫车声、电话约车声、络绎不绝。我们团队私下里也有个微信群,用以和工作的旺旺群区分。<b>在打车软件玩起红包返现后,大家就都会在群里分享叫车红包,52个人的群,有时一分钟内不抢,红包就没了。</b> 32 | <br> 33 | <br> 34 | <br>众所周知的,阿里和快的打车的关系。 35 | <br> 36 | <br>所以群里好像约定俗成般的,从来就没有出现过滴滴的红包。<b>而由于红包返现利滚利带来的超强用户粘性,大家连叫车也都开始只用快的了。</b> 37 | <br> 38 | <img class="shadow" src="/img/in-post/post-kuaidi-1.jpg" width="260"> 39 | 结果好景不长,微信突然就玩了这么一手,直接把快的打车屏蔽了。 40 | <br>当天大家就发现了,还讨论了下对策……<b>比如什么「先分享到微博,然后把链接复制出来,再发到旺旺群」……</b> 41 | <br> 42 | <br>嗯。我 TM 也觉得挺拼的。。 43 | <br>于是大约微信群就沉寂了一天… 44 | <br> 45 | <br><b>然后才第二天……第一个滴滴红包就在群里出现了!</b>那时的文案还是什么:“<i>4个小伙伴,3个用滴滴!红包召唤新伙伴归队啦!</i>” 46 | <br><b>我我我我当时就不由自主的纠结了一会儿 “价值观” ,放下手机 debug 去了……</b> 47 | <br><b>等我再想起来,点开链接一看:特么的……「红包已抢完」。</b> 48 | <br> 49 | <br>。。。 50 | <br><b>再后来。</b><b>就根本收不住了,滴滴红包那个飘。</b> 51 | <br> 52 | <br> 53 | <br>唉其实我就是想说:<b>这也就一天……用户习惯就被彻底干翻过来了。 就算是盟友…也没救。</b> 54 | <br> 55 | <img class="shadow" src="/img/in-post/post-kuaidi-2.jpg" width="260"> 56 | 所以我今天还是打着滴滴回来的……分享红包的一瞬间,心里突然一阵小惆怅。就回来写下了这段答案。 57 | <br> 58 | <br>说了半天,好像也没说到什么干货…权当故事听吧。 59 | <br>其实你要问我这有没有违反互联网平等开放法则什么的。我觉得上面 <a data-hash="8f7d284bb1a97deaa4533a6190206ecb" href="http://www.zhihu.com/people/8f7d284bb1a97deaa4533a6190206ecb" class="member_mention" data-editable="true" data-title="@覃浩tommy" data-tip="p$b$8f7d284bb1a97deaa4533a6190206ecb">@覃浩tommy</a><a data-hash="43d639a3d763d3dad948e0bc4c645eec" href="http://www.zhihu.com/people/43d639a3d763d3dad948e0bc4c645eec" class="member_mention" data-editable="true" data-title="@赛门" data-tip="p$b$43d639a3d763d3dad948e0bc4c645eec">@赛门</a> 都说得挺好的,两种思路而已,大家可以自行选择。 60 | <br> 61 | <br>但是关于怎么看待,其实这次我以普通用户的身份来说……真心觉得:<b>「小良心小正义感在强需求面前真特么太弱了」</b><b>。</b><b>更何况这个强需求被干掉的同时还双手奉上了替代品。</b> 62 | <br> 63 | <br><b><u>所以大厂们你们就使劲撕逼吧,需要打到用户脸时,多给糖多给枣就好了。</u></b> 64 | <br> 65 | <br> 66 | <br>哦对了,今天微信宣布朋友圈内限制分享未备案网页了。 67 | <br><b>枣呢 !?!?</b> 68 | <br> 69 | <br> 70 | </div> 71 | -------------------------------------------------------------------------------- /_posts/2015-03-10-apple-event-2015.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "如何评价 2015 年 3 月 9 日 Apple 春季发布会?" 4 | subtitle: "聊聊科技与新式奢侈品" 5 | date: 2015-03-10 12:00:00 6 | author: "Hux" 7 | hidden: true 8 | header-img: "img/post-bg-apple-event-2015.jpg" 9 | tags: 10 | - 知乎 11 | - 产品 12 | --- 13 | 14 | > 这篇文章转载自[我在知乎上的回答](http://www.zhihu.com/question/28617408/answer/41626694) 15 | 16 | 17 | <div> 18 | <blockquote>一个 gay,一个 gay-like ,带着 Apple 向着<b>新式奢侈品</b>的方向飞去了。</blockquote> 19 | <br>无论是 Apple Watch ,还是 new MacBook,这次发布会都象征着 Apple 更明显的转型。 20 | <br> 21 | <br>不应该再把 Apple 跟 Microsoft 简单粗暴的对比,它们的受众产生了愈大的差异。两家公司对数字时代有着完全不同的战略,它们改变世界的思路,跟盖茨-乔布斯时代比有着更巨大的分歧。 22 | <br> 23 | <br>MS 还是 MS,就像纳德拉 7 月的全员信,微软的战略还是回到了<b>“生产力”。</b>其实微软对“极致”,对“未来”的追求是一种很直观的,我们最初理解的科技,比如手势交互、虚拟现实、机器化自动化、高效办公什么的。微软的受众更多的也还是面向生产力、工作群体(工程师、办公人员)。所以软狗们在知乎永远可以说微软 blah blah,因为对于这部分场景,微软确实有着不可替代的牛逼。 24 | <br> 25 | <br><b>而 Apple 则逐渐转变成为数字时代的 LV。</b>这并不是说它放弃了科技,而是“科技追求极致”的另一种可能性 —— 科技与人文的交汇,甚至是科技与时尚的跨界融合。 26 | <br> 27 | <br>让我们来稍稍想象一下未来: 28 | <br> 29 | <br>科技与生活的融合一定是越来越紧密的。更多的“物件”将与科技结合,而这些智能设备也将越来越普及,它们面向的人群,会越来越宽,直到覆盖所有人。 30 | <br>可以说现在的科技还是很生硬的,我们很容易把科技和 Geek、Nerd 联系在一起。当一个东西和科技沾边时,我们往往会很清楚的意识到:“哦,这是一个科技产品”,于是我们忽略了其他东西,更多的去关注它的科技性(功能性),但是未来不一样。 31 | <br>未来的科技将会很平常,未来的科技将会更加隐形,就像现在的眼镜、家具、衣服、箱包……普通人谁还会在乎它们背后复杂的材料科学与工艺?我们只会觉得它们是生活必需品,然后去在乎它们的外观、舒适性,挑选自己喜欢的产品。 32 | <br> 33 | <br><b>科技也一样,当科技无处不在时,我们对“科技产品”本身的功能性要求,就不再是唯一的考量。</b> 34 | <br> 35 | <br> 36 | <br>LV 的包之所以成为奢侈品,不止是因为“当它作为一个包时,它的功能性(选材、做工)非常优秀,结实耐用”,还因为它的艺术性,观赏性,精致感,幸福感,社会价值等等,带来的种种溢价。 37 | <br> 38 | <br>而 Apple Watch、new MacBook,很明显在做相同的事情。 39 | <br> 40 | <br>说到奢侈,“奢侈”这两个字,在我国基本上是贬义的,词典里的翻译是<b>“挥霍浪费钱财,过分追求享受”</b>,但 Luxury 在英文中其实要中性许多。 41 | <br> 42 | <br>与旧式奢侈相比,新奢侈主义在这一代中产消费者中则被广泛接受。所谓新奢侈主义指的是在同类产品中服务质量更高,品位更高的产品,让消费者心驰神往。它们价格不菲,但是还不至于昂贵到可望不可即。 43 | <br> 44 | <blockquote>德国的实业家拉茨勒在《奢侈带来富足》(2001)一书中对旧式奢侈和新式奢侈做过有趣的论述。他以手机为例说明了两种方式的不同:如果一部手机是因为其先进的技术和为客户提供超值的功能而使价格出众,那么生产和消费这样的手机就是需要倡导的新式奢侈;相反,如果一部手机不是因为卓越的技术性能,而是因为手机套上了嵌有钻石的黄金外壳而使得价格昂贵,那么生产和消费这样的手机就是令人憎恶的旧式奢侈。 45 | <br> 46 | </blockquote>补充一下:<b>这句话出自 2001 年,放在现在来看其实并不是完全适用的。</b> 47 | <br> 48 | <br>手机对当今社会的意义早已不是简单的通讯设备。真正的区别还是在那句话:“Design is about how it works”,<b>新式奢侈的内涵在于产品的某个设计是真的有意义,还是单纯的为了贵而贵。</b> 49 | <br>对于当今数码产品,工业设计、艺术设计是其作为消费品非常重要的部分,如果你是为了给用户提供更多的外观选择而使用黄金,或是为了硬度使用钻石。而不是单纯的堆砌它们来增加价格,那么这些设计都是符合“新式奢侈”的内涵的。 50 | <br> 51 | <br>所以当我们回过头看看 new MacBook,私以为是<b>数字产品界新式奢侈品</b>的典型。 52 | <br> 53 | <br>当我们吐槽 Apple 为了极致的轻薄牺牲了主频、风扇、接口,当我们吐槽买它就是买电池,当我们拿它与 MBA、MBP、Surface 对比吐槽它的 “参数/价钱比” …… 54 | <br> 55 | <br>其实人家的受众是那些有消费能力追求生活质量的 Sir or Lady,它们并不需要天天对着电脑做开发、重型办公或者打游戏,对于只需要便携安静(轻薄+续航+无风扇)、看看电影(Retina Display)、又希望无时不刻彰显自己的品味与身份(外观优雅+极致设计)的他们来说,new Macbook 简直是最适合“佩戴”的轻奢品。 56 | <br> 57 | <br> 58 | <br>有人说 Apple Watch 简直是 Jony Ive 这个一心向往做奢侈品设计的天才将 Apple 引入了歧途里,而我却觉得<b>科技与时尚的结合为何就不是一件美丽的事情?</b> 59 | </div> 60 | -------------------------------------------------------------------------------- /_posts/2015-03-31-e2e_user_scenarios.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Definition of End to End User Scenarios" 4 | date: 2015-03-31 5 | author: "Hux" 6 | header-img: "img/post-bg-e2e-ux.jpg" 7 | published: false 8 | lang: en 9 | tags: 10 | - UX/UI 11 | - En 12 | --- 13 | 14 | 15 | ### End to end? 16 | 17 | To explain what is "End to End User Scenarios", we should first explain what is "End to End", which we can called E2E for short. 18 | 19 | There is not a very clear definition of E2E in wiki.<sup>[[1]](#ref1)</sup> In dictionary, it can both refer to "throughout" or "the end of one object connect to the end of another object".<sup>[[2]](#ref2)</sup> 20 | 21 | E2E is usually used in Logistics, Computer Networking and Software Testing. For example, End-to-end testing is a methodology used to test whether the flow of an application is performing as designed from start to finish. The entire application is tested in a real-world scenario. 22 | 23 | So in my view, the most essential part of E2E is that **we must focus on the entire process, including every parts in a use case.** 24 | 25 | 26 | ### User Scenarios! 27 | 28 | User scenarios is a common term in UX Design,<sup>[[3]](#ref3)</sup><sup>[[4]](#ref4)</sup> which expands upon our persona and user stories by including details. It told us about users' motivation, goals and actions on our products. 29 | 30 | To make it better, there comes **"End to End User Scenarios", not just tell a fragment of users' activities, but pay attention to the entire process the user undergoes.** 31 | 32 | That means we should consider the whole things from the start point that user want to use our products to the ended up point that user get results and leave our products. 33 | 34 | Only when we know **who** does **what** on our products, **how** and **why** they do it, can we define design requirements concrete enough to actually meet them. So it really helps us to improve our UX of our products. 35 | 36 | 37 | ### Let's go deeper... 38 | 39 | We just put the two terms together and give it a explanation, but it can be farther. When we truly design an experience, End to End User Scenarios can helps more: 40 | 41 | * **Extend the scope** 42 | 43 | There is a interesting instance <sup>[[5]](#ref5)</sup> told that sometimes we are already satisfy of our designed UX, but if we look beyond the both ends of the designed experience by extending the scope of the timeline before and after… we may sadly realize that it’s a complete car crash outside the scope of the designed experience... 44 | 45 | Try to extend the scope and consider more, so can we design a much broader experience for our user. 46 | 47 | * **Shorten the path** 48 | 49 | UX Designers always dive into a User Flow and try to shorten the user paths. The idea of End to End User Scenarios can do the same things. 50 | 51 | For example, in the past, if I want to know the weather today. I should typically visit a search engine website, input and search "weather", click the first link that search result page shows, then jump into a kind of weather website like "The Weather Channel", and finally, I got today's weather information! 52 | 53 | But wait! **Just consider it using "End to End User Scenarios"**, I just want to know about weather so I use search engine right? why should I took a so long user path to get there? Smart Search Engine should told me the weather directly. 54 | 55 | That is what all search engine have doing nowadays. 56 | 57 | 58 | ### In sum 59 | 60 | There is many design tools like "End to End User Scenarios" were used by designers, they are really awesome. But the most essential things in my opinion is, still, always thinking about user. All this tools are powerful only based on a truly user-centric mind. 61 | 62 | From my perspective, the "End to End User Scenarios" can be generally defined as **"Entire Process Considered, User Requirement Centric, Anticipated Experince Design".** 63 | 64 | 65 | 66 | That's all, thank you. 67 | 68 | ### References 69 | 70 | 1.<a id="ref1">[End-to-end - Wikipedia, the free encyclopedia](http://en.wikipedia.org/wiki/End-to-end)</a> 71 | 72 | 2.<a id="ref2">[end-to-end - definition of end-to-end by The Free Dictionary](http://www.thefreedictionary.com/end-to-end)</a> 73 | 74 | 3.<a id="ref3">[How User Scenarios Help To Improve Your UX - The Usabilla Blog](http://blog.usabilla.com/how-user-scenarios-help-to-improve-your-ux/)</a> 75 | 76 | 4.<a id="ref4">[How to Create User Stories, Scenarios, and Cases](https://www.newfangled.com/how-to-tell-the-users-story/)</a> 77 | 78 | 5.<a id="ref5">[Designing end-to-end user experiences. | 90 Percent Of Everything](http://www.90percentofeverything.com/2008/11/11/designing-end-to-end-user-experiences/)</a> 79 | -------------------------------------------------------------------------------- /_posts/2015-04-15-os-metro.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "hUX 随想录(二):操作系统的浪漫主义 —— Metro 篇" 4 | subtitle: "信息、载体、抽象、UI 设计乱谈" 5 | date: 2015-04-15 6 | author: "Hux" 7 | header-img: "img/post-bg-os-metro.jpg" 8 | catalog: true 9 | tags: 10 | - hUX 随想录 11 | - UX/UI 12 | --- 13 | 14 | 15 | > 操作系统的背后不只是冷冰冰的 0 和 1 ,数字时代的设计师们,如初神般刻画着新世界的秩序。信息、量子、宇宙,他们取世间万物为灵感来表达自己,那是它们对数字时代最浪漫的隐喻。 16 | 17 | ## 前言 18 | 19 | 操作系统,数字时代当之无愧的地基。当大部分从业人员都更关注它的技术与功能时,操作系统的 UI 设计师们却赋予了它无限的艺术气息:他们用充满着浪漫主义幻想色彩的设计语言,配合着物理定律般严谨的交互体系,描绘着自己心目中的数字世界,那些界面 的背后是他们对数字世界的思考、理解、期待、抽象与隐喻,**这些艺术思想支撑着浮在表面的设计**。他们用一切你熟悉或不熟悉的方式,告诉世人: 20 | 21 | *“看呐,那个虚拟又真实的世界”* 22 | 23 | 24 | ## Metro 25 | 26 | 我们第一个要聊的,就是 [Metro](http://en.wikipedia.org/wiki/Metro_(design_language\)) 。虽然它已经改名为 Modern UI ,虽然它作为 Windows Phone 、Windows 8 甚至 Windows 10 的 UI 风格算不上成功,但是作为一个设计语言,它却是声名显赫。以它而非 Windows 来命名这一章节,就是出于对它的敬意。 27 | 28 |  29 | 30 | 众所周知 Metro 借鉴了交通标示语言、包豪斯现代风格与瑞士国际主义平面设计,其核心思想在于剔除多余信息,专注于内容传达(Content, not chrome),所以 Metro 采用了以 Typography、Color 为主要元素的视觉语言,另外它也非常重视动效设计(Motion Design),这是同期 UI 设计的共识,Motion provides meaning,动效对于表达隐喻有着巨大得作用。 31 | 32 | 我们暂且不去讨论 Metro 在实际运用中的情况,而是尝试去猜想一下 Metro 的设计师们对数字世界的思考,以及那些隐藏在 Metro 背后的奇思妙想: 33 | 34 | #### 思考 —— 极致抽象信息 35 | 36 | 数字时代是基于信息的。这也是为什么我们称这个产业为 IT (Information Technology) ,我们每天使用 PC、Mobile 等数字设备、其实本质是主动或被动的接收、筛选、消化与产生信息。 37 | 38 | 语言与文字的发明是人类信息革命的第一个里程碑,掌握同种语言或文字的人类从此可以高效得进行信息的交换与传播。而现在我们正在走进人机交互与万物互联的时代:人类不但要和人类通信,还要和智能设备建立连接。历史总是上演着重复因此值得借鉴,为什么不把已经发明的东西在数字世界重新发明一次呢?**于是 Cortana 承担了微软在数字时代复刻语音的使命,而 Metro 则继承了老祖宗文字的魔力。** 39 | 40 | 无论 Typography-based 还是 Content, not chrome ,**Metro 试图对一切数字时代的信息进行一种非常极致的抽象 —— 我们的 UI 不需要来自真实世界的隐喻,我们只需要足够直接的信息。** 既然文字就是信息、图片就是信息、音视频就是信息,所以它们理所当然应该直接呈现;而所有的样式也都必须直接传达信息,于是网格和灰度表示层级,颜色的存在也更多代表着符号化的视觉传达:比如用于 VI 的品牌色,或者是刻板印象心情。 41 | 42 | 这种对信息简单粗暴的抽象使得 Metro 的首秀极具冲击,却也成为其日后发展最大的绊脚石。 43 | 44 | 45 | #### 载体 —— 信息平面 46 | 47 | 信息总归需要载体,而设计师们的目的就是寻找,或者创造一种介质来承载、传递、可视化这些信息,然后呈现给用户, 最后才得以成为 UI 48 | 49 | 我们都看着屏幕越来越趋于一种扁平的状态,所有设计师们理所当然的想到这种介质可能是一种类似平面的东西,比如说 WebOS 具有抽象意义的“卡片纸” ,或是 iOS/OS X 改变风格前使用的“亚麻桌布”,他们尝试告诉你藏在屏幕后面的数字世界,可能是由某种类似真实世界的平面状物体来承载信息的。 50 | 而 Metro 则做得更加彻底,在它看来这种拟物是强加给数字世界的不必要信息,于是它抛开了所有自然界存在的元素,又一次将信息抽象做到了极致 :其实那就是一个单纯放置信息的平面而已,或者说,**其实是信息组成了这个平面,数字世界的信息根本无需额外的载体——文字与图像,一方面可以看作是狭义信息的载体,另一方面也可以被看作是广义信息的一种表现形态。** 51 | 52 | **所以我们可以看到 Metro UI 的背景经常是一个空旷的黑色,其实那个黑色代表着 Nothing ,意味着这个平面的下方没有任何东西。**而如果你在下方使用了图像作为背景,你就会发现这其实是两个平面 —— 上层是一个背景透明、漂浮在图像层上的信息平面。而下层则是另一个完全由图像信息组成的信息平面,当我们去划动上层时,产生的视差移动也在告诉我们:这是两个层级。 53 | 54 |  55 | 56 | 在所有的 Metro 组件里,我印象最深刻的叫 Panorama Panel(上图) ,Panorama 在我看来是 Metro 对信息最直接的隐喻:**不同的信息体,聚合成了一个完整的信息平面**。当我们在手机屏幕上左右滑动 Panorama 时就好像在操作一个摄像机平移镜头。这种“数字报纸”区别于报纸的最大感受就好像它可以随着信息的量级在 X 轴和 Y 轴 上无限延伸下去,变成一个信息的海洋,在你的面前流动。 57 | 58 | 对啊,那不就是信息流吗。 59 | 60 | 61 | #### 世界 —— 卡片飞舞的世界 62 | 63 | 我之所以不愿称 Metro 的信息平面为纸片,是因为它不能卷曲也不能折叠; 64 | 而之所以不愿称 Metro 的信息平面为卡片,是因为它并非实体,而且尺寸无限; 65 | 66 | **可 Metro 的世界却又让我觉得是卡片飞舞的。** 67 | 68 | 一张卡片的秩序是动态磁贴(Live Tiles),它很硬,只能翻转。却又具备魔力,好像在每一次的翻转中,信息都可以得到重组和再现。 69 | 二张卡片的秩序是视差原理(Parallax),当你移动镜头时,任意两张卡片在你眼中的位移,都必须由它们距离屏幕 (Z=0) 的深度决定 70 | 三张卡片的秩序就像飞来咒,原有的平面撤离,被呼唤的卡片俏皮的翻滚着从侧后方飞进视野,Metro UI 的动画设计隐喻着一切。 71 | 72 | Status Bar 和 Application Bar 就像是紧贴在屏幕上的卡片,所以不受视差影响。而 Pivot Control 则更有魔幻色彩一点,你操纵它就如操作交通枢纽,指挥一个个小的信息片,来来去去在你的面前。 73 | 74 | 所有这些零厚度的卡片,或近,或远,最终组成了整个 Metro 世界。**在我的想象里,那个次元就好像,所有的信息都以片状飞在空中,而你只能看见你所需要的那些,它们有条不紊的在纵横间穿梭,就好像到处都是信息流的交通轨道,你仿佛置身于,那个数据包飞来飞去、路由器控制地址的 —— 网路世界。** 75 | 76 | 77 |  78 | 79 | 80 | ## 结语 81 | 82 | Metro 对信息极致的抽象与压平,与同期的 iOS 6- 风格形成鲜明对比,引发大家对于数字世界与用户界面的新一轮思考,里程碑式的推动了 Flat Design 在新一代数字设计中的普及。不过我们也知道 Metro UI 在微软的实际运用中却其实不成功,这又是为什么呢? 83 | 84 | 笔者抛砖引玉一些自己的观点: 85 | 86 | 当年 Metro 第一次运用在 Zune 身上时是非常惊艳的,风格超前、细节精致、动画细腻。再看现在的 Xbox (图一),Pivot 配合磁贴组、简单大气,几乎成为电视 UI 设计的模版。可偏偏在 PC 和 Mobile 两个场景,Metro 却饱受非议。 87 | 88 | 在我看来 PC 和 Mobile 其实代表着两个信息密度最高的场景、PC 是传统互联网的计算中心,而 Mobile 则是移动互联网和可以预见的未来内的个人计算中心。 89 | **在如此复杂的场景下,其实 Metro 作为设计语言的尺度是不够的。**为什么这么说呢,虽然 Metro 对信息的抽象方式不无道理,但其实还是过分理想和纯粹了。有太多的屏幕像素因此被浪费,有太多其他维度的信息表达方式因此被舍弃掉了。 90 | 91 | 也就是说:Metro 这个设计语言本身是没有问题的,但是拿目前的它作为 PC/Mobile 这种操作系统级别的设计语言却是存在问题的。**一个操作系统的设计语言与交互体系,一定不能太小,必须是一套包容性足够强又可被拓展和延伸的体系。**其实我们能看到 Windows Phone 的 UI 设计容纳度是非常低的,这或许就可以说明问题。 92 | 93 | **这也是为什么 Win 10 for PC 和 Win 10 for Mobile 都开始削弱最初的那个纯粹的 Metro 体系,转而采用一种 Metro 的视觉语言混搭非 Metro 交互逻辑的方式来设计。** 94 | 期待 new Metro (Metro 2.0) 能在 Win 10 上逐步走向成熟,让我们一同见证。 95 | 96 | --- 97 | 98 | 本文是“操作系统的浪漫主义”系列的第一篇文章,如果您喜欢,请继续关注我的博客 ;) 99 | 100 | 尽请期待: 101 | 102 | * **Android 篇** 103 | * 思考 —— 从卡片的层叠说起 104 | * 载体 —— 量子纸 105 | * 世界 —— 魔法材质统一世界 106 | 107 | * **iOS 篇** 108 | - 思考 —— 盒子里的蒸汽朋克 109 | - 载体 —— 景深的无穷近与无穷远 110 | - 世界 —— 小宇宙里的小宇宙 111 | 112 | 113 | -------------------------------------------------------------------------------- /_posts/2015-05-11-see-u-ali.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "See you, Alibaba " 4 | subtitle: "再见,阿里。" 5 | date: 2015-05-11 6 | author: "Hux" 7 | header-img: "img/post-bg-see-u-ali.jpg" 8 | tags: 9 | - Meta 10 | - 阿里 11 | --- 12 | 13 | 14 | > 世界那么大,我想去看看 15 | 16 | Hi all 17 | 这里是鬼栈的离职信。 18 | 19 |  20 | 21 | 22 | ## Review 23 | 24 | 去年 5 月,大二的我拿到阿里的交互实习生 Offer,成为阿里的实习员工,刚好过去一个年头。 25 | 26 | 8 月,感谢 [@拔赤](http://weibo.com/jayli) 的提携,同意了我转岗到航旅前端团队的申请,分在了老大亲自带队的 **航旅事业群-无线业务部-无线技术-前端团队-前端三组**,从此开始了一名**前端程序猿**的职业生涯。 27 | 28 | 我的第一个 mentor 是大家的"小师妹" @晴舞 姐,不过很可惜的是她居然早于我离职,回北邮任教了。我跟着她在 H5 酒店 的业务线上学习、厮杀,从一个连 git 都用不熟的小小鬼,变成了一个可以独立战斗的小鬼。 29 | 在 Acting H5 酒店/团购 业务线时,也非常感谢 @骏隆 的指导和信任,算是我的大半个 mentor 了。 30 | 31 | 我的第二个 mentor 是人超 nice 的 @智峰 师傅,前手机腾讯网主管,负责团队 CSS 框架,很有生活哲学的一个人。我们一起拿下了 h5 红包等工作,不过很可惜的是没机会从师傅身上学更多的 CSS 了。 32 | 33 | 34 | 有幸来阿里工作一遭,加入航旅前端团队,经历 [离线包/Hybrid容器共建](https://www.zhihu.com/question/31316032/answer/75236718) 这样的牛逼项目,负责过酒店详情、团购详情重构、个人中心红包等工作,为象声汇做过第一版 Logo、海报、颁奖证书,进行过一次团队分享[《聊聊产品与旅行》](http://huxpro.coding.me/2015/06/15/alitrip-strategy/),更有幸认识大家。 35 | 36 | --- 37 | 38 | 在航旅的 270 天里,我还经历了不少**大事件**: 39 | 40 | * 一次 阿里 IPO (千载难逢的大事,可惜我没有股票,战利品是一件纪念 T 恤) 41 | * 一次 新品牌发布 (*阿里旅行·去啊* 的发布,BU 的大事,战利品还是一件 T 恤) 42 | * 一次 年会 (北京 office 第一次大规模年会,马云老陆 Lucy 悉数到场) 43 | * 一次 双十一 (双十一购物狂欢节,有幸从内部参与一次) 44 | * 一次 Outing (每年才一次的公派娱乐,滑雪+温泉记忆深刻) 45 | * 一次 Team Building(晴舞姐的 lastday ,难得的团建) 46 | * 一次 中秋节 (战利品是包装特别用心的“马云牌”月饼) 47 | 48 | 49 | 真的运气非常好,不但该经历的都经历了,连 IPO 这么难得的也撞上了。 50 | 51 |  52 | 53 | 54 | ## To Mates 55 | 56 | 感谢大家这么多天的照顾! 57 | 58 | 无线组的小伙伴们: 59 | 60 | * @拔赤:感谢老大!当年慕名而来,非常感谢“收留” 61 | * @虎牙:超牛的虎牙!非常佩服,人也超 nice ,一直学习的对象 62 | * @兰梦:大姐大!每次问问题都超级热心的解答,非常非常感谢 63 | * @孝瓘:大哥大!技术超牛不说了,对我超级超级好,帮我解答问题送我回家什么的,特别感动。 64 | * @豹子:双子座美女姐姐哈哈,前两天生日快乐哦,队花 BU 花! 65 | * @弘树:简直学霸 & 学神!超年轻超钻,感觉以后会是阿里前端顶梁柱人物哟 66 | * @若狸:猫爷!京腔儿~虽然总是在朋友圈骂 PD 不过其实特别靠谱活儿特别好哈哈哈 67 | * @圣耀:首页守护神!加班时你总是在,然后一起分吃,的再去苦逼干活 OTZ 68 | * @智峰:叶师傅!虽然总是不让我叫师兄互相学习云云,不过真的跟我说了很多人生哲理,超受用 69 | * @擎黄:麦霸!特别聊得来,缘分大概最早来自于坐我旁边,你和舒博搬走时我超舍不得的 T T 你还记得你拿我机箱垫脚吗! 70 | * @舒博:同上都是 90 后,聊得来!经常一起吃饭,Outing 的时候睡一屋,晚上打鼾完早上还会问我然后道歉特别萌哈哈哈 71 | * @骏隆:分不清你是哪组!不过一起共事一起玩经常一起吃饭,特别 nice,非常非常感谢,一起做酒店时非常开心! 72 | * @夕剑:虽然已经离职了看不到不过必须补上,机票的代名词!超 nice 超靠谱,又帅又有趣 73 | * @晴舞:虽然已经离职了看不到不过必须补上,特别感谢的师姐,最难的开头都是你带我走过去的 74 | * @已过:虽然已经转岗了看不到不过必须补上,一度觉得很像大反派!印象最深的就是刚进来 git 写错了看我 log 帮我回滚 OTZ,当时觉得特别凶 75 | * @清锁:实习生小伙伴!你居然先我离职了喂。不过我知道你都签三方啦 76 | 77 | 其他组的我就捡比较熟悉的说啦: 78 | 79 | * @银翘:校友师姐!特别萌,负责象声汇特别尽心尽力 80 | * @皓勋:充满战斗力的小伙伴!超级青春洋溢,看好你哟~! 81 | * @懂象:Hey Flasher!Flasher 果然都爱动画爱交互,很聊得来~ 82 | * @龙芒:好像一起打过球?哈哈哈其实没有原因就是觉得特别可爱! 83 | * @伯元:咦是离职了吗?一起打过好久的球! 84 | 85 | 当然,还有很多前端、UED 、测试、后端、行政 的小伙伴们,就没法一一照顾到啦。 86 | 87 | **希望所有人都能工作顺利(少加班)、生活开心(多旅游)、身体健康哈。** 88 | 89 | ## Future 90 | 91 | 距离毕业还有一年多的光景,前路未卜,还是想到处逛逛,多看看再做选择。 92 | 93 | 在陆续看了几家公司后,我决定前往**微信电影票**开始我的下一段旅程。特别巧的是,带队的饼饼居然也曾是我们团队的“老人”,花名 @痴灵 94 | 95 | 世界这么大,更要 Keep Contact. 96 | 97 | * 微博:@Hux黄玄 98 | * 知乎:@黄玄 99 | * 博客:<http://huangxuan.me> 100 | 101 | 102 | **Hey,这里是编号 79717** 103 | 104 |  105 | -------------------------------------------------------------------------------- /_posts/2015-07-09-js-module-7day.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: keynote 3 | title: "JavaScript 模块化七日谈" 4 | subtitle: "🎞 Slides:JavaScript Modularization Journey" 5 | iframe: "//huangxuan.me/js-module-7day/" 6 | date: 2015-07-09 7 | author: "Hux" 8 | tags: 9 | - Slides 10 | - Web 11 | - JavaScript 12 | --- 13 | 14 | 15 | > 下滑这里查看更多内容 16 | 17 | 7月9日,我在公司内部进行了名为「JavaScript 模块化七日谈」分享,并将该 Slides 分享到了微博上。出乎意料地,这篇微博先后被 @JS小组 @尤小右 @寸志 等近 200 人转发,阅读达到 10w,获得了还不错的评价。 18 | 19 | 于是,我决定将它重新发到我的博客上,并为它专门制作了适用于 Keynote 展示文稿的新布局。它能自动根据屏幕大小/旋转以一定比例填充屏幕,你也可以直接点击下方链接在新页面打开,来获得更好的、沉浸式的全屏体验 20 | 21 | 22 | ### [Watch Fullscreen →](https://huangxuan.me/js-module-7day/) 23 | 24 | <div class="visible-md visible-lg"> 25 | <img src="//huangxuan.me/js-module-7day/attach/qrcode.png" width="350"/> 26 | <small class="img-hint">你也可以通过扫描二维码在手机上观看</small> 27 | </div> 28 | 29 | 30 | 这个 Web Slides 开源在[我的 Github 上](https://github.com/Huxpro/js-module-7day),欢迎你帮助我完善这个展示文稿,你可以给我提 issue,可以 fork & pull request。如果它能帮助到你了,希望你还能不吝啬 star 一下这个项目 31 | 32 | 33 | ### Catalog 34 | 35 | - 第一日 上古时期 ***Module?*** 从设计模式说起 36 | - 第二日 石器时代 ***Script Loader*** 只有封装性可不够,我们还需要加载 37 | - 第三日 蒸汽朋克 ***Module Loader*** 模块化架构的工业革命 38 | - 第四日 号角吹响 ***CommonJS*** 征服世界的第一步是跳出浏览器 39 | - 第五日 双塔奇兵 ***AMD/CMD*** 浏览器环境模块化方案 40 | - 第六日 精灵宝钻 ***Browserify/Webpack*** 大势所趋,去掉这层包裹! 41 | - 第七日 王者归来 ***ES6 Module*** 最后的战役 42 | 43 | ### Thanks 44 | 45 | [Reveal.js](http://lab.hakim.se/reveal-js) 46 | -------------------------------------------------------------------------------- /_posts/2015-09-22-js-version.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "「译」ES5, ES6, ES2016, ES.Next: JavaScript 的版本是怎么回事?" 4 | subtitle: "ES5, ES6, ES2016, ES.Next: What's going on with JavaScript versioning?" 5 | date: 2015-09-22 6 | author: "Hux" 7 | header-img: "img/post-bg-js-version.jpg" 8 | tags: 9 | - Web 10 | - JavaScript 11 | - 译 12 | --- 13 | 14 | 15 | JavaScript 有着很奇怪的命名史。 16 | 17 | 1995 年,它作为网景浏览器(Netscape Navigator)的一部分首次发布,网景给这个新语言命名为 LiveScript。一年后,为了搭上当时媒体热炒 Java 的顺风车,临时改名为了 JavaScript *(当然,Java 和 JavaScript 的关系,就和雷锋和雷锋塔一样 —— 并没有什么关系)* 18 | 19 |  20 | <small class="img-hint">歪果仁的笑话怎么一点都不好笑</small> 21 | 22 | > 译者注:[wikipedia 的 JavaScript 词条](https://en.wikipedia.org/wiki/JavaScript#History) 更详细的叙述了这段历史 23 | 24 | 1996 年,网景将 JavaScript 提交给 [ECMA International(欧洲计算机制造商协会)](http://www.ecma-international.org/) 进行标准化,并最终确定出新的语言标准,它就是 ECMAScript。自此,ECMAScript 成为所有 JavaScript 实现的基础,不过,由于 JavaScript 名字的历史原因和市场原因(很显然 ECMAScript 这个名字并不令人喜欢……),现实中我们只用 ECMAScript 称呼标准,平时都还是使用 JavaScript 来称呼这个语言。 25 | 26 | 27 | > 术语(译者注): 28 | > 29 | > * *标准(Standard)*: 用于定义与其他事物区别的一套规则 30 | > * *实现(Implementation)*: 某个标准的具体实施/真实实践 31 | 32 | 33 | 不过,JavaScript 开发者们并不怎么在乎这些,因为在诞生之后的 15 年里,ECMAScript 并没有多少变化,而且现实中的很多实现都已经和标准大相径庭。其实在第一版的 ECMAScript 发布后,很快又跟进发布了两个版本,但是自从 1999 年 ECMAScript 3 发布后,十年内都没有任何改动被成功添加到官方规范里。取而代之的,是各大浏览器厂商们争先进行自己的语言拓展,web 开发者们别无选择只能去尝试并且支持这些 API。即使是在 2009 年 ECMAScript 5 发布之后,仍然用了数年这些新规范才得到了浏览器的广泛支持,可是大部分开发者还是写着 ECMAScript 3 风格的代码,并不觉得有必要去了解这些规范。 34 | 35 | > 译者注:[ECMAScript 第四版草案](https://en.wikipedia.org/wiki/ECMAScript#4th_Edition_.28abandoned.29)由于太过激进而被抛弃,Adobe 的 [ActionScript 3.0](https://en.wikipedia.org/wiki/ActionScript) 是 ECMAScript edition 4 的唯一实现( Flash 差点就统一 Web 了) 36 | 37 | 到了 2012 年,事情突然开始有了转变。大家开始推动停止对旧版本 IE 浏览器的支持,用 ECMAScript 5 (ES5) 风格来编写代码也变得更加可行。与此同时,一个新的 ECMAScript 规范也开始启动。到了这时,大家开始逐渐习惯以对 ECMAScript 规范的版本支持程度来形容各种 JavaScript 实现。在正式被指名为 ECMAScript 第 6 版 (ES6) 之前,这个新的标准原本被称为 ES.Harmony(和谐)。2015 年,负责制定 ECMAScript 规范草案的委员会 TC39 决定将定义新标准的制度改为一年一次,这意味着每个新特性一旦被批准就可以添加,而不像以往一样,规范只有在整个草案完成,所有特性都没问题后才能被定稿。因此,ECMAScript 第 6 版在六月份公布之前,又被重命名为了 ECMAScript 2015(ES2015) 38 | 39 | 目前,仍然有很多新的 JavaScript 特性或语法正在提议中,包括 [decorators(装饰者)](https://github.com/wycats/javascript-decorators),[async-await(async-await 异步编程模型)](https://github.com/lukehoban/ecmascript-asyncawait) 和 [static class properties(静态类属性)](https://github.com/jeffmo/es-class-properties)。它们通常被称为 ES7,ES2016 或者 ES.Next 的特性,不过实际上它们只能被称作提案或者说可能性,毕竟 ES2016 的规范还没有完成,有可能全部都会引入,也有可能一个都没有。TC39 把一个提案分为 4 个阶段,你可以在 [Babel 的官网](https://babeljs.io/docs/usage/experimental/) 上查看各个提案目前都在哪个阶段了。 40 | 41 | 所以,我们该如何使用这一大堆术语呢?下面的列表或许能帮助到你: 42 | 43 | * **ECMAScript**:一个由 ECMA International 进行标准化,TC39 委员会进行监督的语言。通常用于指代标准本身。 44 | * **JavaScript**:ECMAScript 标准的各种实现的最常用称呼。这个术语并不局限于某个特定版本的 ECMAScript 规范,并且可能被用于任何不同程度的任意版本的 ECMAScript 的实现。 45 | * **ECMAScript 5 (ES5)**:ECMAScript 的第五版修订,于 2009 年完成标准化。这个规范在所有现代浏览器中都相当完全的实现了。 46 | * **ECMAScript 6 (ES6) / ECMAScript 2015 (ES2015)**:ECMAScript 的第六版修订,于 2015 年完成标准化。这个标准被部分实现于大部分现代浏览器。可以查阅[这张兼容性表](http://kangax.github.io/compat-table/es6/)来查看不同浏览器和工具的实现情况。 47 | * **ECMAScript 2016**:预计的第七版 ECMAScript 修订,计划于明年夏季发布。这份规范具体将包含哪些特性还没有最终确定 48 | * **ECMAScript Proposals**:被考虑加入未来版本 ECMAScript 标准的特性与语法提案,他们需要经历五个阶段:Strawman(稻草人),Proposal(提议),Draft(草案),Candidate(候选)以及 Finished (完成)。 49 | 50 | 在这整个 Blog 中,我将把目前的 ECMAScript 版本称作 ES6(因为这是大部分开发者最习以为常的),把明年的规范称作 ES2016(因为,与 ES6/ES2015 不同,这个名字将在整个标准化过程中沿用)并且将那些还没有成为 ECMAScript 定稿或草案的未来语言概念称为 ECMAScript 提案或者 JavaScript 提案。我将尽我所能在任何可能引起困惑的场合沿用这篇文章。 51 | 52 | #### 一些资源 53 | 54 | 55 | 56 | * TC39 的 [Github 仓库](https://github.com/tc39/ecma262)上可以看到所有目前公开的提案 57 | * 如果你还不熟悉 ES6,Babel 有一个[很不错的特性概览](https://babeljs.io/docs/learn-es2015/) 58 | * 如果你希望深入 ES6,这里有两本很不错的书: Axel Rauschmayer 的 [Exploring ES6](http://exploringjs.com/)和 Nicholas Zakas 的 [Understanding ECMAScript 6](https://leanpub.com/understandinges6)。Axel 的博客 [2ality](http://www.2ality.com/) 也是很不错的 ES6 资源 59 | 60 | <img class="shadow" width="320" src="/img/in-post/post-js-version/keep-calm-and-learn-javascript.png" /> 61 | <small class="img-hint">来学 JavaScript 吧!</small> 62 | 63 | #### 著作权声明 64 | 65 | 本文译自 [ES5, ES6, ES2016, ES.Next: What's going on with JavaScript versioning?](http://benmccormick.org/2015/09/14/es5-es6-es2016-es-next-whats-going-on-with-javascript-versioning/) 66 | 译者 [黄玄](http://weibo.com/huxpro),首次发布于 [Hux Blog](http://huangxuan.me),转载请保留以上链接 67 | 68 | -------------------------------------------------------------------------------- /_posts/2015-12-28-css-sucks-2015.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: keynote 3 | title: "都 2015 年了,CSS 怎么还是这么糟糕" 4 | subtitle: "🎞 Slides:CSS Still Sucks 2015" 5 | iframe: "//huangxuan.me/css-sucks-2015/" 6 | date: 2015-12-28 7 | author: "Hux" 8 | tags: 9 | - Web 10 | - CSS 11 | --- 12 | 13 | 14 | > 下滑这里查看更多内容 15 | 16 | 17 | ### [Watching Fullscreen →](https://huangxuan.me/css-sucks-2015/) 18 | 19 | <div class="visible-md visible-lg"> 20 | <img src="//huangxuan.me/css-sucks-2015/attach/qrcode.png" width="350"/> 21 | <small class="img-hint">你也可以通过扫描二维码在手机上观看</small> 22 | </div> 23 | 24 | 25 | 这个 Web Slides 开源在[我的 Github 上](https://github.com/Huxpro/css-sucks-2015),欢迎你帮助我完善这个展示文稿,你可以给我提 issue,可以 fork & pull request。如果它能帮助到你了,希望你还能不吝啬 star 一下这个项目 26 | 27 | 28 | ### Catalog 29 | 30 | - Document Times 31 | - Frameworks 32 | - Style Guide 33 | - **OOCSS** 34 | - **SMACSS** 35 | - **Pre-processer** 36 | - **PostCSS** 37 | - Application Times 38 | - **Shadow DOM** 39 | - **CSS "4"** 40 | - Naming Convention 41 | - **BEM** 42 | - **SUIT** 43 | - **Atomic CSS** 44 | - **CSS in JS** 45 | - **CSS Modules** 46 | - Interoperable CSS 47 | - PostCSS, again 48 | - My Opinionated Proposal 49 | - **POCss** 50 | 51 | ## POCss: Page Override Components CSS 52 | 53 | ### 1. Scoping Components <br><small style="line-height:2em;">*CSS Blocks should only be used inside a component of the same name.*</small> 54 | 55 | ```scss 56 | // Component/index.scss 57 | .ComponentName { 58 | &--mofierName {} 59 | &__decendentName { 60 | &--modifierName {} 61 | } 62 | .isStateOfComponent {} 63 | } 64 | ``` 65 | 66 | ```javascript 67 | // Component/index.js 68 | require('./index.scss'); 69 | ``` 70 | 71 | CSS is *always bundled* with components<br>(from loading, mount to unmount) 72 | 73 | ### 2. Components can be Overrode by Pages <br><small style="line-height:2em;">*There is always requirements to rewrite styles of components in pages*</small> 74 | 75 | ```scss 76 | // Pages/PageA.scss 77 | #PageA { 78 | .pagelet-name { 79 | .pagelet-descendent-name {} 80 | } 81 | .ComponentName{ /* override */ } 82 | } 83 | ``` 84 | 85 | ```javascript 86 | // Pages/index.js 87 | require('./PageA.scss'); 88 | ``` 89 | 90 | - *#Page* for absolutely scoping between pages 91 | - *.pagelet-name* should be lowercase to prevent conflicting with components 92 | 93 | ### Why POC? 94 | 95 | - **It's technology-agnostic** 96 | <small> 97 | *One css framework can be played with whatever technology stacks*<br> 98 | *You can combined Scss, PostCSS and whatever you want* 99 | </small> 100 | 101 | - **Solving problems, and easy** 102 | <small> 103 | *Makes reading and teamwork much easier*<br> 104 | *Get all benefit from BEM, SUITCSS and others* 105 | </small> 106 | 107 | - **Leverage the power of cascading properly** 108 | <small> 109 | *Scoping components but allow reasonable overriding*<br> 110 | *It's pragmatic, flexible and hitting the sweet spot* 111 | </small> 112 | 113 | ### Thanks 114 | 115 | [Reveal.js](http://lab.hakim.se/reveal-js) 116 | -------------------------------------------------------------------------------- /_posts/2016-06-05-pwa-in-my-pov.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: keynote 3 | title: "Progressive Web App 之我见" 4 | subtitle: "🎞 Slides:Progressive Web App, in my points of view" 5 | iframe: "//huangxuan.me/pwa-in-my-pov/" 6 | nav-style: "invert" 7 | date: 2016-06-05 8 | author: "Hux" 9 | tags: 10 | - Slides 11 | - Web 12 | - PWA 13 | --- 14 | 15 | 16 | > 下滑这里查看更多内容 17 | 18 | ### [Watching Fullscreen →](https://huangxuan.me/pwa-in-my-pov/) 19 | 20 | <div class="visible-md visible-lg"> 21 | <img src="//huangxuan.me/pwa-in-my-pov/attach/qrcode.png" width="350" /> 22 | <small class="img-hint">Scanning on mobile</small> 23 | </div> 24 | 25 | 26 | ### Catalog 27 | 28 | - WHAT is Progressive Web App? 29 | - 1 - Installability 30 | - 2 - App Shell 31 | - 3 - Offline 32 | - SERVICE WORKER! 33 | - 4 - Re-engageable 34 | - Push Notification 35 | - CONS in my pov 36 | - PROS in my pov 37 | - Why Web? 38 | 39 | 40 | ### Power by [Yanshuo.io(演说.io)](https://yanshuo.io) 41 | -------------------------------------------------------------------------------- /_posts/2016-09-22-the-open-web.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Web 在继续离我们远去" 4 | subtitle: "After the release of Wechat Mini-Program" 5 | author: "Hux" 6 | header-img: "img/post-bg-web.jpg" 7 | header-mask: 0.4 8 | tags: 9 | - Web 10 | - 微信 11 | --- 12 | 13 | > 本文首发于我的知乎专栏 [The Little Programmer](https://zhuanlan.zhihu.com/p/22561084),转载请保留链接 ;) 14 | 15 | 今天微信又刷爆了我的朋友圈 —— 小程序,之前传说的应用号。 16 | 17 | 不过这篇不谈小程序的技术细节,也不去猜测(因为知道得很清楚……), 18 | 19 | 也不谈小程序会对中国互联网带来什么影响(自有产品经理会来谈……), 20 | 21 | 我们说说 Web,the Web。 22 | 23 | 我们常说的 Web,其实是 World Wide Web 的简称 the Web 的简称。 24 | 25 | 跟 H5 一样,这货是个简称的简称,所以简到最后就没人知道它本身是个什么意思了。 26 | 27 | 不要说中国老百姓分不清万维网和互联网了,美国老百姓也一样分不清 Web 和 Internet, 28 | 29 | 很多不求甚解的从业人士也好不到哪去,Web 常年在技术文章中被翻译得不知所云。 30 | 31 | 中文世界里把这件事讲得最清楚也最在乎的,非 [@不鳥萬如一](//www.zhihu.com/people/6bec872206d9884cd9535841b6a1f510) 莫属了。 32 | 33 | 比如在[《一天世界》博客:微信并不是在「管理」外部链接,因为微信公众号在事实上(de facto)不允许任何外部链接 - 不鳥萬通讯 - 知乎专栏](https://zhuanlan.zhihu.com/p/20747514) 里他写到: 34 | 35 | > 中文世界一直混淆[互联网](https://en.wikipedia.org/wiki/Internet)(internet)和[万维网](https://en.wikipedia.org/wiki/World_Wide_Web)(web)。人们念兹在兹的「互联网开放精神」,实乃万维网的开放精神。万维网的开放主要就体现在一点:**任何万维网上的文章之间都可以通过网址随意互相链接**。如果我想在文章里介绍 UbuWeb 这个网站,我就可以直接在 [UbuWeb](https://ubu.com/) 这六个字母上添加它的网址 ubu.com。妳或许觉得这是废话,但在微信公众号的文章里妳做不到;妳只能添加微信生态圈内的链接,比如这个:[https://weixin.qq.com/cgi-bin/readtemplate?t=weixin_external_links_content_management_specification](https://weixin.qq.com/cgi-bin/readtemplate%3Ft%3Dweixin_external_links_content_management_specification)(即上述《规范》的链接) 36 | 37 | 所以如一卸了微信( [告别微信 一天世界](https://blog.yitianshijie.net/2016/02/21/byebye-wechat/) )还写了:[微信——事实上的局域网](https://blog.yitianshijie.net/2015/11/16/wechat-de-facto-lan/) ,嗯,作为一个愈发对 Open Web 这件事 hardcore 的人来说,我是认同的。 38 | 39 | 如一最在乎的可能是文章,而我更在乎的是应用,Web App。 40 | 41 | 所谓 Web App,是 Web 的一种进化:从提供文本信息(超文本)到多媒体(超媒体)到提供软件应用服务。硬核的翻译过来大概是“基于万维网的应用”,比如你在 Web 浏览器中使用的 Youtube、Twitter、Medium、Github 等等,**它们之间仍然可以通过网址(URL)随意互相链接,遵循 Web 开放标准,并且你几乎可以在任何一个具备浏览器的平台上使用这项服务,因此 Web App 同样是开放的。** 42 | 43 | 如果你听说过 Google 的 Progressive Web Apps,它其实代表的是 Progressive Open Web Apps,只是这样实在太长太啰嗦了。 44 | 45 | 毕竟,Web 的概念里理应包含着 Open。 46 | 47 | (这篇文章的本意并不是为了 advocate PWA,但如果你对 PWA 有兴趣,欢迎阅读: [黄玄:下一代 Web 应用模型 — Progressive Web Appzhuanlan.zhihu.com!](https://zhuanlan.zhihu.com/p/25167289) 48 | 49 | 如果说 Hybrid 架构还只是 Web 理想主义的一次让步,那么 React Native 的出现则无疑让部分人的信仰崩塌,然后是 Weex,然后可能是你们猜的微信。 50 | 51 | 眼见 “以 Web 范式为 Native 平台进行开发” 的方式越来越火,虽然受益的好像是 Web 前端从业人员,可我却不知该不该开心。 52 | 53 | 我不是说它们是“错误的技术方向”,从实用主义来说它们很棒,很解决问题。 54 | 55 | **但是,无论他们长得有多像 Web,他们都不是 Open Web 平台的一员。** 56 | 57 | RN/Weex 根本没有 URL(别跟我说 Universal Links 或 App Links,URL 和 URI 是不同的) 58 | 59 | 而微信从 JS-SDK 开始,便已经是一个封闭生态了。 60 | 61 | 这种势头虽然缘起于 Facebook,却更可能在中国撒起野来。 62 | 63 | 英文世界里对这类事情敏感/hardcore 的人很多,比如写了 [Regressive Web Apps](https://adactio.com/journal/10708) 的 Jeremy Keith,因为 PWA 对 URL 不够友好的事情跟 Chrome 开发老大 Alex 吵了一架,而 Alex 也急得说出了: 64 | 65 | > so, your choices are to think that I have a secret plan to kill URLs, or conclude I’m still Team Web. 66 | 67 | 要知道,Alex 带着 Chrome 搞 PWA 的原因就是看不爽 Hybrid 破坏了 Open Web。 68 | 69 | 倘若 Twitter/FB 跟微信一样连链接还不让随便链,大概都得弃用 Twitter,然后像如一一样火冒三丈的写一篇 Byebye Twitter/FB。 70 | 71 | 而国内天天鼓吹得什么 XX 助力 HTML5 生态,却不知大部分时候这些所谓 “HTML5 生态” 都是和 Web 生态背道而驰的,高下立判。 72 | 73 | 我开始有些语无伦次了。 74 | 75 | 在这个 HTML5 与 Web 被极度误用的中文世界里,我也不知道该如何呐喊了。 76 | 77 | 我只知道,当 Web 只能作为 Native 的 "Markup Language" 存活时,Web 也就不复存在了。 78 | 79 | 当大家都不跟随 Web 标准自造一套时,Web 所谓的跨平台特性也就烟消云散了。 80 | 81 | 我之前写过的,Chrome 产品 Leader Rahul 也在 I/O 上说过得: 82 | 83 | Web 的 Dicoverable、Linkable、Low Friction、Broad Reach 等等,这些都不是 Web 的本质,**Web 的本质是 Open(开放)与 Decentralized (去中心化),这才是万维网(WWW)的初衷,这才是所有这些特性能成立的前提。** 84 | 85 | Open Web 的信仰让浏览器厂商们重新走到了一起,他们在问你: 86 | 87 | **Hey, can we make the web great again?** 88 | -------------------------------------------------------------------------------- /_posts/2016-10-20-pwa-qcon2016.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: keynote 3 | title: "Progressive Web Apps,复兴序章「QCon 上海 2016」" 4 | subtitle: "🎞 Slides:Progressive Web Apps, Make Web Great Again. (QCon Shanghai 2016)" 5 | iframe: "//huangxuan.me/pwa-qcon2016/" 6 | navcolor: "invert" 7 | date: 2016-10-20 8 | author: "Hux" 9 | tags: 10 | - Slides 11 | - Web 12 | - PWA 13 | --- 14 | 15 | 16 | > 下滑这里查看更多内容 17 | 18 | 19 | ### [Watching Fullscreen →](https://huangxuan.me/pwa-qcon2016/) 20 | 21 | ### [Watching Video →](http://www.infoq.com/cn/presentations/progressive-web-app) 22 | 23 | <div class="visible-md visible-lg"> 24 | <img src="//huangxuan.me/pwa-qcon2016/attach/qrcode.png" width="350" /> 25 | <small class="img-hint">Scanning on mobile</small> 26 | </div> 27 | 28 | 29 | ### Catalog 30 | 31 | - The State Of Web 32 | - Rethinking Hybridzation 33 | - PWA 101 34 | - Definition 35 | - Add To HomeScreen 36 | - Web Manifest 37 | - Reliable Experience (Network as PE) 38 | - Service Worker 39 | - Register SW 40 | - On Install & Cache API 41 | - ExtendableEvent & SkipWaiting 42 | - On Fetch 43 | - Stale-While-Revalidate & Fallback 44 | - Updating SW 45 | - SW LifeCycle 46 | - On Activate 47 | - SW Brings Architectural Revolution 48 | - Re-engageable 49 | - PWA In Production 50 | - User Expectation & Guiding 51 | - Low Deliver Friction 52 | - PWA vs. Others 53 | - The Belief In Web 54 | - One Web 55 | - Fulfill WWDC 2007 56 | 57 | 58 | ### Notes 59 | 60 | This slides is powered by [Yanshuo.io (演说.io)](http://yanshuo.io), a online software helping you create, store and share web slides. 61 | 62 | `index.html` is the HTML source code exported from [Yanshuo.io](http://yanshuo.io), and many of its dependencis (js, css, fonts) are still linked to CDN of [Yanshuo.io](http://yanshuo.io). You can do any secondary development and host it by yourself. 63 | 64 | 65 | -------------------------------------------------------------------------------- /_posts/2016-11-20-sw-101-gdgdf.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: keynote 3 | title: "Service Worker 101「GDG DevFest 2016 北京」" 4 | subtitle: "🎞 Slides:Service Worker 101, Working Offline and Instant Loading (GDG DevFest 2016 Beijing)" 5 | iframe: "//huangxuan.me/sw-101-gdgdf/" 6 | navcolor: "invert" 7 | date: 2016-11-20 8 | author: "Hux" 9 | tags: 10 | - Slides 11 | - Web 12 | - PWA 13 | --- 14 | 15 | 16 | > 下滑这里查看更多内容 17 | 18 | 19 | TLDR; It covers lots of cool stuff about Service Worker! 20 | 21 | ### [Watching Fullscreen → ](https://huangxuan.me/sw-101-gdgdf/) 22 | 23 | <div class="visible-md visible-lg"> 24 | <img src="//huangxuan.me/sw-101-gdgdf/attach/qrcode.png" width="350" /> 25 | <small class="img-hint">Scanning on mobile</small> 26 | </div> 27 | 28 | 29 | 30 | ### [Demo Code → ](https://github.com/Huxpro/sw-101-gdgdf) 31 | 32 | - Hello World of Service Worker 33 | - Make your own Offline Dinosaurs 34 | - Stale/Fastest while revalidate 35 | 36 | 37 | 38 | ### Notes 39 | 40 | This slides is powered by [Yanshuo.io (演说.io)](http://yanshuo.io), a online software helping you create, store and share web slides. 41 | 42 | There are 2 ways that you can fork or contribute this project: 43 | 44 | 1. `index.html` is the HTML source code exported from [Yanshuo.io](http://yanshuo.io), and many of its dependencis (js, css, fonts) are still linked to CDN of [Yanshuo.io](http://yanshuo.io). You can do any secondary development and host it by yourself. 45 | 2. Download the project file under `shuo/`, drag it into [Yanshuo.io](http://yanshuo.io), and you are ready to go. You can edit whatever you want, upload it to your account, and even share your distributions. 46 | 47 | 48 | -------------------------------------------------------------------------------- /_posts/2017-04-06-html-document.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: 如何理解 <code>document</code> 对象是 <code>HTMLDocument</code> 的实例? 4 | subtitle: Why is <code>document</code> an instance of <code>HTMLDocument</code>? 5 | author: "Hux" 6 | header-style: text 7 | tags: 8 | - Web 9 | - 知乎 10 | --- 11 | 12 | > 这篇文章转载自[我在知乎上的回答](https://www.zhihu.com/question/57601873/answer/155685476) 13 | 14 | 谢邀。 15 | 16 | 首先要理解的是 DOM 是 API,是一组无关编程语言的接口(Interfaces)而非实现(Implementation)。前端平时常说的 DOM 其实只是浏览器通过 ECMAScript(JavaScript)对 DOM 接口的一种实现。 17 | 18 | 其次要知道的是,DOM 既是为 HTML 制定的,也是为 XML 制定的。而两者各有一些特异的部分,所以作为 DOM 标准基石的 DOM Level 1 其实分为 Core 与 HTML 两个部分。Core 定义了 fundamental interfaces 与 extended interfaces,分别是共用的基础接口与 「XML 拓展包」,而 HTML 部分则全都是「HTML 拓展包」。题主所问到的 Document 接口被定义在 Core 的 fundamental interfaces 中,而 HTMLDocument 接口则定义在 HTML 部分中,且「接口继承」于 Document。 19 | 20 | 这种继承关系当然是可以在 JavaScript 的 DOM 实现中体现出来的: 21 | 22 | ```js 23 | // document 是 HTMLDocument 的实例 24 | document instanceof HTMLDocument // true 25 | 26 | // document 的 [[prototype]] 指向 HTMLDocument 的原型 27 | document.__proto__ === HTMLDocument.prototype // true 28 | 29 | // HTMLDocument 伪类继承于 Document 30 | HTMLDocument.prototype instanceof Document // true 31 | HTMLDocument.prototype.__proto__ === Document.prototype // true 32 | ``` 33 | 34 | 至于 Document 与 HTMLDocument 这两个构造函数,跟 Array、Object 一样都是 built-in 的: 35 | 36 | ```js 37 | > Document 38 | < function Document() { [native code] } 39 | > HTMLDocument 40 | < function HTMLDocument() { [native code] } 41 | ``` 42 | 43 | 虽然是 native code,但一个有意思的现象是,这两个构造函数之间也是存在原型链的: 44 | 45 | ```js 46 | // HTMLDocument 的 [[prototype]] 是指向 Document 的 47 | HTMLDocument.__proto__ == Document 48 | 49 | // 同理 50 | Document.__proto__ == Node 51 | Node.__proto__ == EventTarget 52 | ``` 53 | 54 | 其作用是实现对静态成员的继承。( ES6 Class 的行为与此完全一致,但这个行为在更早之前就是这样了。) 55 | 56 | 好了扯远了,总结一下,**在 JavaScript 的 DOM 实现中** 57 | 58 | * document 是 HTMLDocument 的实例 59 | * HTMLDocument 继承于 Document 60 | 61 | 留一个课后作业,有兴趣的话可以看看 Document.prototype 与 HTMLDocument.prototype 里分别都有什么?在不同浏览器里都试试。 62 | 63 | 以上。 64 | -------------------------------------------------------------------------------- /_posts/2017-06-25-you-are-slaves.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "他是狗,你们便是苟奴隶" 4 | date: 2017-06-24 12:00:00 5 | author: "Hux" 6 | header-style: text 7 | catalog: false 8 | published: false 9 | tags: 10 | - 被夹 11 | --- 12 | 13 | > 在知乎被删帖,我理解知乎。 14 | > 你说你们做不了什么,我也理解你们。 15 | > <br/> 16 | > 只是,总要有人,还敢说点反对的声音吧? 17 | > 只是,不想让这一切,看起来都变得如此理所应当吧? 18 | > <br/> 19 | > 你说,你们也抗争了 20 | > 那就站出来,让我们相信,你们还在吧? 21 | 22 | 我甚至都不需要写出「刘国梁」这三个顶天立地的大字,你们便知道我今天要说什么了。 23 | 骂狗官、骂体制、骂 D,骂的人已经够多了。我故是可以再骂,却也深知自己甚至连让他们听到这份声音的能力都没有。 24 | 25 | **但今天,我要骂的是你们,至少还能听到我声音的你们。** 我亲爱的同行们啊,那些在微博、知乎与其他社交网络公司工作的你们啊。无论你是我推心置腹的好友,相识或共事过的伙伴,还是素未谋面的陌生人,对不起,今天我要骂的就是你们。 26 | 27 | 微博,「随时随地发现新鲜事」,可这个这世界却只能发生你审核过的新鲜事。 28 | 29 | 知乎,「发现更大的世界」,可我们却只能发现你审核过的世界。 30 | 31 | 好一个又一个讲着漂亮故事的互联网公司啊,你们不是打着 UGC、言论开放的旗号、沾着民智渐开,民主自由的福利吗?好一个又一个独立自强、新时代的互联网员工啊,你们不是为「建设了中国互联网」,打造了一个「用户喜爱的产品」而感到自豪吗? 32 | 33 | 嘴上说着不要,身体却已经跪在金钱与权势之下任人驱使了嘛。 34 | 35 | **这种情况,我们一般称之为「奴隶」。** 36 | 37 | > 奴隶,通常指失去人身自由并被他人任意驱使的,为他们做事的人。 38 | 39 | --- 40 | 41 | 你可以跟我喊冤,说你也想反抗过,说你也很无奈。说你也思考过政府和媒体的关系,说你也知道权利、体制的可怖与强大,说你不能承担反抗的后果。 42 | 43 | 可难道那些国乒远动员们不知道吗?从小成长在体制内的他们,比你清楚得多太多了。可是为了自己的权利、自己的公平,自己的爱,他们还是集体站出来了啊!他们直面着比你大得多的体制压力,承受着可能影响他们一生的严重后果。你告诉他们应该隐忍?识大体?沉默?那叫做苟且,叫做冷血,叫做向暴政与不公屈服!他们也知道,在体制面前他们势单力薄,可能是以卵击石头。可是他们仍然不顾一切的发声,那是在请求我们的帮助啊! 44 | 45 | 而你现在却还在问我你为什么要怪罪我,而不去怪罪那些「上面」的人? 46 | 47 | 我当然也怪罪「上面」的人!但是你们,是你们!直接挡住了他们的求救,挡住了人民的援助,挡住了人民发声的渠道啊!传统媒体是 D 的喉舌,而你们呢,为自由奋斗的你们呢?你们本该成为人民的耳朵、眼睛和嘴啊,现在却愿意让人民都成为聋子、瞎子、哑巴了吗? 48 | 49 | 你们或许觉得一己之力无法改变任何事情,于是沉默,每个人都沉默,仿佛罪恶都被平摊了,到每个人身上就都接近于 0 了。仿佛这一切就都理所应当了,可是真的就理所应当了吗? 50 | 51 | **一群人在作恶时,每个个体就不是在作恶了吗!?** 52 | 53 | **天再黑也要说话啊。** 54 | 55 | <br /> 56 | 57 | 58 | 我是一个胖球迷,从小就是。初中、高中、大学一路在校队打着酱油,参加一些业余的小比赛。很多人说在中国会打点胖球没什么稀奇,这是国球。很多人说打胖球不帅,女生们都围着打篮球的转。可是没办法,我就是喜欢,床头贴着 LGL 带着二王一马拿下世乒赛的海报,家里的《乒乓世界》一垛又一垛,一直到现在也不舍得扔。 59 | 60 | 我是一个程序员,从小就是。在几家公司打过酱油,做过一些小分享。很多人说程序员都是农民,天天干一些重复的事情,加班多,死得早。可是没办法,我就是喜欢,喜欢互联网这个崇尚自由与平等的地方,欣赏那些用互联网让世界变得更加美好的人们。我不是为了谋生而选择了这个职业,我是为了自由与骄傲。 61 | 62 | > We will not go quietly into the night! 63 | > We will not vanish without a fight! 64 | > We're going to live on! 65 | > We're going to survive! 66 | > Today, we celebrate our Independence Day! 67 | 68 | **国乒,愿有属于你们的独立日。** 69 | -------------------------------------------------------------------------------- /_posts/2017-07-12-upgrading-eleme-to-pwa.markdown: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "饿了么的 PWA 升级实践" 4 | subtitle: "Upgrading Ele.me to Progressive Web App" 5 | date: 2017-07-12 12:00:00 6 | author: "Hux" 7 | header-img: "img/in-post/post-eleme-pwa/eleme-at-io.jpg" 8 | header-mask: 0.3 9 | catalog: true 10 | multilingual: true 11 | tags: 12 | - Web 13 | - PWA 14 | --- 15 | 16 | <!-- Chinese Version --> 17 | <div class="zh post-container"> 18 | {% capture about_zh %}{% include posts/2017-07-12-upgrading-eleme-to-pwa/zh.md %}{% endcapture %} 19 | {{ about_zh | markdownify }} 20 | </div> 21 | 22 | <!-- English Version --> 23 | <div class="en post-container"> 24 | {% capture about_en %}{% include posts/2017-07-12-upgrading-eleme-to-pwa/en.md %}{% endcapture %} 25 | {{ about_en | markdownify }} 26 | </div> 27 | -------------------------------------------------------------------------------- /_posts/2017-07-26-farewell-flash.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Farewell, Flash. 感谢你,但这一次是真正的永别。" 4 | subtitle: "So long, and thanks for all the Flash" 5 | author: "Hux" 6 | header-img: "img/post-bg-farewell-flash.jpg" 7 | header-mask: 0.2 8 | tags: 9 | - Web 10 | - Flash 11 | --- 12 | 13 | > 本文首发于我的知乎专栏 [The Little Programmer](https://zhuanlan.zhihu.com/p/28109200),转载请保留链接 ;) 14 | 15 | 一年半前,我曾和 Flash 作过一次告别。那一次,Adobe Flash Professional CC 被重新命名为了 Adobe Animate CC,宣告着 Flash 作为一个创作工具走到了尽头。 16 | 17 | 18 |  19 | 20 | 21 | 22 | 而今天,通过 Chromium 博客 [So long, and thanks for all the Flash](https://blog.chromium.org/2017/07/so-long-and-thanks-for-all-flash.html) 我才得知,Adobe 官博在 [Flash & The Future of Interactive Content](https://blogs.adobe.com/conversations/2017/07/adobe-flash-update.html) 一文中,宣布将在 2020 年底时停止发布与更新 Flash Player。这一次,意味着 Flash 作为一个平台走到了尽头。 23 | 24 | 25 | 26 | 在不少人眼里,Flash 与 HTML5 是纯粹的竞争关系,我们应该为 HTML5 与 Open Web 标准的胜利欢呼,而将 Flash 狠狠的咒骂在黄泉之下。但其实,大多数人都忘记了,或是从不曾知道:**HTML5(严谨的来说,其 marketing 含义中所涵盖的那些 Web APIs),有很大一部分正是 Flash 平台、Flash 社区对 web 标准做出的贡献。** 27 | 28 | 正如 [Flash & The Future of Interactive Content](https://blogs.adobe.com/conversations/2017/07/adobe-flash-update.html) 所说: 29 | 30 | > Adobe has long played a leadership role in advancing interactivity and creative content – from video, to games and more – on the web. Where we’ve seen a need to push content and interactivity forward, we’ve innovated to meet those needs. **Where a format didn’t exist, we invented one – such as with Flash and Shockwave. And over time, as the web evolved, these new formats were adopted by the community, in some cases formed the basis for open standards, and became an essential part of the web.** 31 | 32 | 当我们(企业、用户)需要 web 平台承载包括视频、游戏在内的各种富交互内容而 web 平台本身还不具备这样的能力时,我们通过给予这个平台一种新的格式,以满足大家的需求,这就是 Flash Player,作为一种私有平台与浏览器插件,却能一度成为 web 事实标准的客观原因。 33 | 34 | 而时至今日,这些 web 平台所欠缺的能力,在得到市场与社区的认可之后,逐渐被从 Flash 中吸收与扬弃,成为了诸如 HTML5 Video/Audio/Canvas、WebGL 这些真正的 Open Web 标准。这时候,这些在诞生之初颇为创新的,作为了一种「过渡手段」、「Shim」的私有平台,便自然而然的,慢慢的不再被需要了。 35 | 36 | **这并不应该理解为一种失败,而应该说,它们「功成身退」了。** 37 | 38 | <br/> 39 | 40 | ActionScript 3.0,Flash 中的御用编程语言,作为 ES4 的唯一实现,[推动了 ECMAScript 标准的发展,深远得影响着现代 JavaScript](https://www.zhihu.com/question/49170215/answer/114640341); 41 | 42 | Adobe Flex,Flash 平台的企业开发框架,在今年和 [@徐飞](https://www.zhihu.com/people/sharpmaster) 老师聊到时,还一起怀念并认可其相比现代 web 前端/客户端开发在工具链、协作、兼容性、UI 组件等方面的先进与成熟; 43 | Adobe AIR,作为最早借鉴 JRT 将 web 相关技术的 Runtime 植入操作系统或捆绑在可执行文件内的跨平台开发方案,或许可以视作 Cordova、Electron、NodeWebkit、ReactNative 这些方案的一个前身与成功先例; 44 | 45 | Microsoft IE 私有技术 ActiveX 中的 XMLHTTP,作为 XMLHTTPRequest 的前身,促进了 Ajax 的诞生与 Web 2.0 时代的来临; 46 | 47 | Google Gears 作为 2008 年时为了增强 web 应用的浏览器插件,其私有 API 分别是 App Cache、Web Worker、WebSQL 等标准或标准未遂的前身; 48 | 49 | Cordova/Phonegap 作为第一个面向移动端的 Hybrid 方案,成为了 web 开发与移动设备的 polyfill 与桥梁,加速了 Web 平台 Device APIs 的发展,并与 WebOS、FirefoxOS、Chrome Apps、Windows Runtime Apps 等一同影响了 Progressive Web App 的出现; 50 | 51 | Google Extension 中 Background Page 与 Event Page 多年对 web 平台后台持续计算的尝试,直接帮助了 Service Worker 的 API 设计; 52 | 53 | Google 的 NativeClient、Mozilla 的 asm.js 对于 web 追逐 native 性能的极致追求,则奠定了 Web Assembly 的诞生…… 54 | 55 | 你看,在这条道路上,Flash 与它的朋友们,其实并不孤单。 56 | 57 | **「看到你长大了,我也就可以心满意足的离开了。」** 58 | 59 | **就像是, web 技术发展的必然规律一样,** 60 | 61 | **而 Open Web 则因此不朽。** 62 | 63 | <br/> 64 | 65 | 我很高兴,Google Chrome、Mozilla Firefox、Microsoft Edge 都能这么写到: 66 | 67 | > Flash helped make the web a rich, dynamic experience, and **shaped the modern set of web standards.** 68 | > 69 | > --- "[So long, and thanks for all the Flash](https://blog.chromium.org/2017/07/so-long-and-thanks-for-all-flash.html)" Chromium Blog 70 | 71 | 72 | 73 | > Over the years, Flash has helped bring the Web to greatness with innovations in media and animation, **which ultimately have been added to the core web platform.** 74 | > 75 | > --- "[Firefox Roadmap for Flash End-of-Life](https://blog.mozilla.org/futurereleases/2017/07/25/firefox-roadmap-flash-end-life/)" Mozilla Blog 76 | 77 | 78 | 79 | > Flash led the way on the web for rich content, gaming, animations, and media of all kinds, and **inspired many of the current web standards powering HTML5.** 80 | > 81 | > --- "[The End of an Era – Next Steps for Adobe Flash](https://blogs.windows.com/msedgedev/2017/07/25/flash-on-windows-timeline/)" Windows Blog 82 | 83 | 84 | 85 | 感谢你,Flash。 86 | 87 | 感谢你们,那些「功成身退」的你们。 -------------------------------------------------------------------------------- /_posts/2017-10-06-css-complaints.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "为什么 CSS 这么难学?" 4 | subtitle: "Why I dislike CSS as a programming language" 5 | author: "Hux" 6 | header-img: "img/post-bg-css.jpg" 7 | header-img-credit: "@WebdesignerDepot" 8 | header-img-credit-href: "medium.com/@WebdesignerDepot/poll-should-css-become-more-like-a-programming-language-c74eb26a4270" 9 | header-mask: 0.4 10 | tags: 11 | - Web 12 | - CSS 13 | - 知乎 14 | --- 15 | 16 | > 这篇文章转载自[我在知乎上的回答](https://www.zhihu.com/question/66167982/answer/240434582) 17 | 18 | 对我来说,CSS 难学以及烦人是因为它**「出乎我意料之外的复杂」**且让我觉得**「定位矛盾」**。 19 | 20 | [@方应杭](//www.zhihu.com/people/b90c7eb6d3d5a4e2ce453dd8ad377672) 老师的答案我赞了:CSS 的属性互不正交,大量的依赖与耦合难以记忆。 21 | 22 | [@顾轶灵](//www.zhihu.com/people/596c0a5fdd9b36cea06bac348d418824) [@王成](//www.zhihu.com/people/c02ec74a44ee4a6784d002c33e293652) 说得也没错:CSS 的很多规则是贯彻整个体系的,而且都记在规范里了,是有规律的,你应该好好读文档而不是去瞎试。 23 | 24 | 25 | 「**CSS是一门正儿八经的编程语言,请拿出你学C++或者Java的态度对待它**」 26 | 27 | 但是问题就在这了,无论从我刚学习前端还是到现在,我都没有把 CSS 作为一门正儿八经的编程语言(**而且显然图灵不完全的它也不是**),CSS 在我眼里一直就是一个布局、定义视觉样式用的 DSL,与 HTML 一样就是一个标记语言。 28 | 29 | 写 CSS 很有趣,CSS 中像继承、类、伪类这样的设计确实非常迎合程序员的思路,各种排列组合带来了很多表达上的灵活性。但如果可以选择,在生产环境里我更愿意像 iOS/Android/Windows 开发那样,把这门 DSL 作为 IDE WYSIWYG 编辑器的编译目标就可以了,当然你可以直接编辑生成的代码,但我希望「对于同一种效果,有比较确定的 CSS 表达方式」 30 | 31 | 因为我并不在 CSS 里处理数据结构,写算法、业务逻辑啊,我就是希望我能很精确得表达我想要的视觉效果就可以了。如果我需要更复杂的灵活性和控制,你可以用真正的编程语言来给我暴露 API,而不是在 CSS 里给我更多的「表达能力」 32 | 33 | 34 | **CSS 语言本身的表达能力对于布局 DSL 来说是过剩的**,所以你仅仅用 CSS 的一个很小的子集就可以在 React Native 里搞定 iOS/Android 的布局了。你会发现各个社区(典型如 React)、团队都要花很多时间去找自己项目适合的那个 CSS 子集(so called 最佳实践)。而且 CSS 的这种复杂度其实还挺严重得影响了浏览器的渲染性能,很多优化变得很难做。 35 | 36 | **而 CSS 的表达能力对于编程语言来说又严重不够**,一是语言特性不够,所以社区才会青睐 Less、Sass 这些编译到 CSS 的语言,然后 CSS 自己也在加不痛不痒的 Variable。二是 API 不够,就算你把规范读了,你会发现底层 CSSOM 的 Layout、Rendering 的东西你都只能强行用声明式的方式去 hack(比如用 transform 开新的 composition layer)而没有真正的 API 可以用,所以 W3C 才会去搞 Houdini 出来。 37 | 38 | 这种不上不下的感觉就让我觉得很「矛盾」,你既没法把 CSS 当一个很简单的布局标记语言去使用,又没办法把它作为一个像样的编程语言去学习和使用。 39 | 40 | 41 | 在写 CSS 和 debug CSS 的时候我经常处在一种「MD 就这样吧反正下次还要改」和「MD 这里凭什么是这样的我要研究下」的精分状态,可是明明我写 CSS 最有成就感的时候是看到漂亮的 UI 啊。 42 | 43 | 以上。 44 | -------------------------------------------------------------------------------- /_posts/2017-12-12-halting-problem.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "如何通俗地解释停机问题?" 4 | subtitle: "How to explain the Halting Problem?" 5 | author: "Hux" 6 | header-img: "img/post-bg-halting.jpg" 7 | header-mask: 0.3 8 | tags: 9 | - 知乎 10 | - 计算理论 11 | --- 12 | 13 | > 这篇文章转载自[我在知乎上的回答]( https://www.zhihu.com/question/20081359/answer/275107187) 14 | 15 | 我用 Python 伪代码来解释下,我觉得对这个问题有兴趣的应该都是有点编程基础的,所以直接上 code 应该是最容易的。 16 | 17 | ## 背景知识 18 | 19 | 「停机问题」研究的是:是否存在一个「程序」,能够判断另外一个「程序」在特定的「输入」下,是会给出结果(停机),还是会无限执行下去(不停机)。 20 | 21 | 在下文中,我们用「函数」来表示「程序」,「函数返回」即表示给出了结果。 22 | 23 | ## 正文 24 | 25 | 我们假设存在这么一个「停机程序」,不管它是怎么实现的,但是它能够回答「停机问题」:它接受一个「程序」和一个「输入」,然后判断这个「程序」在这个「输入」下是否能给出结果: 26 | 27 | ```py 28 | def is_halt(program, input) -> bool: 29 | # 返回 True 如果 program(input) 会返回 30 | # 返回 False 如果 program(input) 不返回 31 | ``` 32 | 33 | (在这里,我们通过把一个函数作为另一个函数的输入来描述一个「程序」作为另一个「程序」的「输入」,如果你不熟悉「头等函数」的概念,你可以把所有文中的函数对应为一个具备该函数的对象。) 34 | 35 | 为了帮助大家理解这个「停机程序」的功能,我们举个使用它的例子: 36 | 37 | ```py 38 | from halt import is_halt 39 | 40 | def loop(): 41 | while(True): 42 | pass 43 | 44 | # 如果输入是 0,返回,否则无限循环 45 | def foo(input): 46 | if input == 0: 47 | return 48 | else: 49 | loop() 50 | 51 | is_halt(foo, 0) # 返回 True 52 | is_halt(foo, 1) # 返回 False 53 | ``` 54 | 55 | 是不是很棒? 56 | 57 | 不过,如果这个「停机程序」真的存在,那么我就可以写出这么一个「hack 程序」: 58 | 59 | ```py 60 | from halt import is_halt 61 | 62 | def loop(): 63 | while(True): 64 | pass 65 | 66 | def hack(program): 67 | if is_halt(program, program): 68 | loop() 69 | else: 70 | return 71 | ``` 72 | 73 | 这个程序说,如果你 `is_halt` 对 `program(program)` 判停了,我就无限循环;如果你判它不停,我就立刻返回。 74 | 75 | 那么,如果我们把「hack 程序」同时当做「程序」和「输入」喂给「停机程序」,会怎么样呢? 76 | 77 | ```py 78 | is_halt(hack, hack) 79 | ``` 80 | 81 | 你会发现,如果「停机程序」认为 `hack(hack)` 会给出结果,即 `is_halt(hack, hack)`) 返回 `True`) ,那么实际上 `hack(hack)` 会进入无限循环。而如果「停机程序」认为 `hack(hack)` 不会给出结果,即 `is_halt(hack, hack)` 返回 ,那么实际上 `hack(hack)` 会立刻返回结果…… 82 | 83 | 这里就出现了矛盾和悖论,所以我们只能认为,我们最开始的假设是错的: 84 | 85 | **这个「停机程序」是不存在的。** 86 | 87 | ## 意义 88 | 89 | 简单的说,「停机问题」说明了现代计算机并不是无所不能的。 90 | 91 | 上面的例子看上去是刻意使用「自我指涉」来进行反证的,但这只是为了证明方便。实际上,现实中与「停机问题」一样是现代计算机「不可解」的问题还有很多,比如所有「判断一个程序是否会在某输入下怎么样?」的算法、Hilbert 第十问题等等,wikipedia 甚至有一个 [List of undecidable problems](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/List_of_undecidable_problems)。 92 | 93 | ## 漫谈 94 | 95 | 如果你觉得只是看懂了这个反证法没什么意思: 96 | 97 | 1. 最初图灵提出「停机问题」只是针对「图灵机」本身的,但是其意义可以被推广到所有「算法」、「程序」、「现代计算机」甚至是「量子计算机」。 98 | 2. 实际上「图灵机」只能接受(纸带上的)字符串,所以在图灵机编程中,无论是「输入」还是另一个「图灵机」,都是通过编码来表示的。 99 | 3. 「图灵机的计算能力和现代计算机是等价的」,更严谨一些,由于图灵机作为一个假象的计算模型,其储存空间是无限大的,而真实计算机则有硬件限制,所以我们只能说「不存在比图灵机计算能力更强的真实计算机」。 100 | 4. 这里的「计算能力」(power)指的是「能够计算怎样的问题」(capablity)而非「计算效率」(efficiency),比如我们说「上下文无关文法」比「正则表达式」的「计算能力」强因为它能解决更多的计算问题。 101 | 5. 「图灵机」作为一种计算模型形式化了「什么是算法」这个问题([邱奇-图灵论题](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Church%25E2%2580%2593Turing_thesis))。但图灵机并不是唯一的计算模型,其他计算模型包括「[Lambda 算子](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Lambda_calculus)」、[μ-递归函数](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/%25CE%259C-recursive_function)」等,它们在计算能力上都是与「图灵机」等价的。因此,我们可以用「图灵机」来证明「[可计算函数](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Computable_function)」的上界。也因此可以证明哪些计算问题是超出上界的(即不可解的)。 102 | 6. 需要知道的是,只有「可计算的」才叫做「算法」。 103 | 7. 「停机问题」响应了「哥德尔的不完备性定理」。 104 | 105 | ## 拓展阅读: 106 | 107 | 中文: 108 | 109 | - [Matrix67: 不可解问题(Undecidable Decision Problem)](https://link.zhihu.com/?target=http%3A//www.matrix67.com/blog/archives/55) 110 | 111 | - [Matrix67: 停机问题、Chaitin 常数与万能证明方法](https://link.zhihu.com/?target=http%3A//www.matrix67.com/blog/archives/901) 112 | 113 | - [刘未鹏:康托尔、哥德尔、图灵--永恒的金色对角线(rev#2) - CSDN 博客](https://link.zhihu.com/?target=http%3A//blog.csdn.net/pongba/article/details/1336028) 114 | 115 | - [卢昌海:Hilbert 第十问题漫谈 (上)](https://link.zhihu.com/?target=http%3A//www.changhai.org/articles/science/mathematics/hilbert10/1.php) 116 | 117 | 英文: 118 | 119 | - [《Introduction to the Theory of Computation》](https://link.zhihu.com/?target=https%3A//en.wikipedia.org/wiki/Introduction_to_the_Theory_of_Computation) 120 | 121 | - [Turing Machines Explained - Computerphile](https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DdNRDvLACg5Q) 122 | 123 | - [Turing & The Halting Problem - Computerphile](https://link.zhihu.com/?target=https%3A//www.youtube.com/watch%3Fv%3DmacM_MtS_w4%26t%3D29s) 124 | 125 | - [Why, really, is the Halting Problem so important?](https://link.zhihu.com/?target=https%3A//cs.stackexchange.com/questions/32845/why-really-is-the-halting-problem-so-important) 126 | -------------------------------------------------------------------------------- /_posts/2017-12-12-uncomputable-funcs.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "如何证明不可计算的函数比可计算的函数多?" 4 | subtitle: "Why is there more uncomputable functions?" 5 | author: "Hux" 6 | header-img: "img/post-bg-infinity.jpg" 7 | header-mask: 0.3 8 | mathjax: true 9 | tags: 10 | - 知乎 11 | - 计算理论 12 | --- 13 | 14 | > 这篇文章转载自[我在知乎上的回答](https://www.zhihu.com/question/51508063/answer/275401076) 15 | 16 | 严谨的证明的话,可以使用「形式语言」([Formal language](https://en.wikipedia.org/wiki/Formal_language))来证明: 17 | 18 | 在可计算理论和计算复杂度理论中,每个「计算问题」都被描述为一个一个「形式语言」,即字符串的集合。比如对于判断一个图是否是无向连通图这个问题:我们可以写为一个描述所有无向连通图的集合: 19 | 20 | $ 21 | A = \{ \langle G \rangle \vert G \text{ is a connected undirected graph}\} 22 | $ 23 | 24 | 由于图灵机只能接受字符串,所以这里的尖括号表示对图的「编码」。出于简单,我们全部使用现实计算机所使用的字母表 25 | $\Sigma = \\{0, 1\\}$,所以「编码」即一个对象的二进制字符串描述。 26 | 27 | 如果我们能构造出一个图灵机来「决定」这个「形式语言」,即可以判断一个「输入」是否属于这个集合(membership 与 non-membership),那么我们可以说我们用「图灵机」描述了一个「算法」来计算这个问题,而这个「计算问题」所对应的函数是「可计算的」,否则是「不可计算的」。(注 1) 28 | 29 | 那么,如果我们有一个包含了所有「可计算函数」的集合,这个集合会有多大呢? 30 | 31 | <br> 32 | 33 | 由于 34 | 35 | - 所有「可计算函数」总有一个对应的「图灵机」来计算它 36 | - 每一个「图灵机」都可以被「编码」为一个不同的 0、1 序列,比如 000,010... 37 | - 0、1 序列、即二进制,总是可以被转换为一个十进制数的 38 | 39 | 所以,我们这个集合实际上是与整数集 $Z$ 一样大(等势)的,我们把这个集合表示为 $\Sigma^{\*}$。 易知 $Z$ 是「无穷可数(countably infinite)」的,所以我们有无穷可数个「可计算函数」(注 2)。 40 | 41 | <br> 42 | 43 | 而「计算问题」有多少个呢? 44 | 45 | 这个问题可以等同于,我们有多少个形如 $\\{000, 010\\}$ 这样的 0,1 序列的集合?即 $\Sigma^{\*}$ 这个集合有多少个子集?用数学语言描述就是求 $\Sigma^{\*}$ 的幂集的势 $\| P(\Sigma^{\*})\|$ 。 46 | 47 | 由于 $\Sigma^{\*}$ 与 $Z$ 是等势的,所以这个问题等价于求 $\|P(Z)\|$ 的大小。根据 [Cantor's theorem](https://en.wikipedia.org/wiki/Cantor%2527s_theorem),一个「无穷可数」的集合的幂集是「无穷不可数(uncountably infinite)」的。(注 3) 48 | 49 | <br> 50 | 51 | 根据 [Cantor's theorem](https://en.wikipedia.org/wiki/Cantor%2527s_theorem),「无穷不可数集」要比「无穷可数集」大。 52 | 53 | 同时,「无穷不可数集」减去「无穷可数集」后仍然是「无穷不可数集」。(注 4) 54 | 55 | 所以,「不可计算函数集」,即「计算问题集」与「可计算函数集」的差,仍是「无穷不可数集」,仍比是为「无穷可数集」的「可计算函数集」大。 56 | 57 | 因此,「不可计算的函数」比「可计算的函数」多。 58 | 59 | 证毕。 60 | 61 | <br> 62 | 63 | 注: 64 | 65 | 1. 「[可计算函数](https://en.wikipedia.org/wiki/Computable_function)」是算法的直觉说法,「[邱奇-图灵论题](https://en.wikipedia.org/wiki/Church%25E2%2580%2593Turing_thesis)」猜想任何在算法上可计算的问题同样可以由图灵机计算。但图灵机并不是唯一的计算模型,其他计算模型包括「[Lambda 算子](https://en.wikipedia.org/wiki/Lambda_calculus)」、「$\mu$ - [递归函数](https://en.wikipedia.org/wiki/%25CE%259C-recursive_function)」等,它们在计算能力上都是与「图灵机」等价的。 66 | 2. 证明「所有可计算函数」的集合是「无穷可数集」的方式有很多,只要找到任意一个与「自然数集」的「双射」即可 67 | 3. 也可以直接用康托的对角线法([Cantor's diagonal argument](https://en.wikipedia.org/wiki/Cantor%2527s_diagonal_argument))证明「所有计算问题」的集合是「无穷不可数集」 68 | 4. 可以用反证法得证 69 | 5. 知乎能用 LaTex 了好评 70 | 6. [Aleph Number - Wikipedia](https://en.wikipedia.org/wiki/Aleph_number) 71 | -------------------------------------------------------------------------------- /_posts/2018-05-11-pwa-zh-preface.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "《PWA 实战》推荐序" 4 | date: 2018-05-11 12:00:00 5 | author: "Hux" 6 | header-style: text 7 | catalog: true 8 | tags: 9 | - Web 10 | - PWA 11 | --- 12 | 13 | > 「博文视点」邀请我给[《PWA实战:面向下一代的Progressive Web APP》](https://union-click.jd.com/jdc?e=&p=AyIGZRhfEgoaBVUbXBYyEgRXHF8UChI3EUQDS10iXhBeGlcJDBkNXg9JHU4YDk5ER1xOGRNLGEEcVV8BXURFUFdfC0RVU1JRUy1OVxUBEABRGlMVMmZMDxwsR2cWZVdbO2ocFV9cSB5qfnILWStaJQITBlcTWhYLEQJlK1sSMkRpVRpaFAMTAlUeWCUDIgdSG1oXARIPUx5eFAMiAFUSaxYBFAJVElgSCw4FURxTFAoiN2UYayUyEjdWKxl7UEEPUR5dFFYWBgYTXhZXFA5WTlMSVxoDUh9TQFFBAVUrWRQDFg4%3D) 写的推荐序。 14 | 15 | Progressive Web App 是继 Ajax、响应式设计、HTML5 之后,web 平台的又一次革命性突破。它在开放 Web 标准的基础之上,突破了以往 Web 应用只能「依赖互联网分发」与「依赖浏览器为入口」的两大桎梏,一下子打开了 Web 应用从性能、架构到用户体验上的一系列可能性。 16 | 17 | PWA 中最引入注目的核心新特性,Service Worker,实质上是为 Web 应用带来了一种安全而又低功耗的后台处理能力。无论是用于实现离线 Web 应用所需要的缓存读写与网络代理,还是用于提升 Web 应用能力的推送通知、后台同步,其实都得益于这种新的并发能力。随着 Edge 与 Safari 的相继发布,Service Worker 已经历史性的达到了全浏览器的支持。 18 | 19 | 而这就要归功于 Web 开放性的力量。相比于其他众多私有的“类 Web”技术,PWA 技术完全属于开放 Web 标准。PWA 因此具备了独一无二的跨平台能力,不止于移动端,Chrome 与 Windows 已经让 PWA 在桌面端也晋升为了第一公民。这使得「一套代码,发布可以同时跨移动桌面设备、跨操作系统、跨浏览器的超级应用」真正成为可能。这里有非常大的想象空间,非常值得我们期待。 20 | 21 | PWA 作为“下一代 Web 应用模型”从 2015 年第一次发布,到现在的 2018 年中,国际上 Google、Twitter、Facebook、Instagram、FlipKart、Uber、Lyft、Pinterest、Tinder、Flipboard、Spotify……国内诸如 AliExpress、饿了么、微博,都已经在使用 PWA 技术甚至发布了专门的 PWA 产品。可以说 PWA 从生态到工具链都已经逐渐成熟,接下来将会迎来更大的爆发。 22 | 23 | 在这个时间点上,很高兴能看到本书的翻译团队能在如此短的时间里将最新的技术带回中文社区,非常难能可贵。本人也做过一些 PWA 的分享,但要对社区带来更大的推动,我们更需要这样完整的大部头作品。 24 | 25 | 本书原著非常详实且不失生动地涵盖了 PWA 的方方面面。作者不但通过一个贯穿全书的案例将 PWA 的各项技术串起,还把它们所要解决的问题与可以带来的产品价值也一一娓娓道来。书中讨论到的策略与模式非常实用,既可以帮助你快速上手 PWA,也能帮助你对 Web 应用的工程化有更好的理解。 26 | 27 | 在此,我谨作为整个中文 Web 社区的一员,感谢团队的贡献! 28 | -------------------------------------------------------------------------------- /_posts/2018-06-30-dreamer.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "程序员中的梦想家" 4 | subtitle: "Dreamers among programmers" 5 | author: "Hux" 6 | header-img: "img/post-bg-dreamer.jpg" 7 | header-mask: 0.4 8 | tags: 9 | - Facebook 10 | - Meta 11 | --- 12 | 13 | > 本文首发于我的知乎专栏 [The Little Programmer](https://zhuanlan.zhihu.com/p/38722466),转载请保留链接 ;) 14 | 15 | 有一类程序员是 visionary 型的,为了实现一些超前的 idea,绕过某些技术的限制,他们写的 code 晦涩高深得只有他们自己能懂,做出来的 tool 看上去很美好结果处处是坑出了 bug 根本没法查,但正是这类人不断创造出新的东西,在洗礼之后成为一个个 big thing。 16 | 17 | 我每周都要被 infra 的坑 block 得无法工作几次搞得非常沮丧,后来我发现这个锅除了要扔给 FB 外,还有一大半要扔给我周围这群 visionary 的同事们,我工作直接需要接触到的区区五六个人,发起/创造了 Infer, React, Reason, ReasonReact, BuckleScript... 18 | 19 | 所以这大概就是见证/参与这些 idea 成长的代价吧,也意识到这些东西不是在刚开始就像后来大家接受流行时那么美好的。React 发布 5 周年生日时回放 Jordan/Tom 2013 年第一次对外发布 React/JSX 的视频。我问 Jordan 说你后来怎么没再去分享了。他说你不知道我那天讲完下来被所有听众指着批评。React 第一次在内部使用是 2011 年在 news feed,然后是 2012 年 instagram (pete hunt),所以这个时间其实很长很长。 20 | 21 | 很多人(包括我)都会经常觉得 XYZ 新事物跟老东西比太新、太不成熟、体验太不好、想要解决的问题太多、解决方案太 overkill、然后就没有然后了,但其实说不定你在看的这个就是 next big thing 呢。这些梦想家们 vision 里的 big picture 太大了,有的人可能在半个 picture 出来的时候就可以看出来了,有的人则可能要等到整个 picture 都快填满了才看得出来。 22 | 23 | 如果不是因为 Ads/Messenger 的坑深 React/Reason/Flux 也就不会在这里诞生了, 24 | 25 | 如果不是因为 Facebook 的坑深 GraphQL/Infer/Hack/Flow/Buck 也就不会在这里诞生了。 26 | 27 | 正是有一群开垦者不怕坑深才使得各种 idea 成为了大家手上好用的 tool 啊。 28 | 29 | 梦想家程序员们的工作价值于实干主义的程序员,总是很容易在过程中被低估、忽视,或是得不到尊重。而又在流行之后被神化,仿佛是那个人早已洞察一切一样。其实梦想家的工作,也是一点点累加,一点点迭代起来的。他们也需要伯乐和追随者的支持和帮助。 30 | 31 | Chenglou 这个人总是在巨兴奋与巨沮丧之间切换,这段时间下来,我开始能感受这种情绪的来源了。 32 | 33 | 他总是用一句话来总结他回答我的吐槽、抱怨、疑问、惊叹,我就用这句话来结尾好了: 34 | 35 | **"Welcome to the producer side!"** 36 | -------------------------------------------------------------------------------- /_posts/2018-10-06-vim-cn-im.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "Vim 与中文输入法" 4 | subtitle: 'Using Vim with non-english input method' 5 | author: "Hux" 6 | header-style: text 7 | tags: 8 | - Vim 9 | --- 10 | 11 | Update: 我最后还是放弃把 Vim 作为主要编辑器来输入中文了,整体使用下来 mental model 的 cost 太重了。记笔记时用用中文呀或者改改博客时偶尔用一下还蛮去,这个时候这个功能至少能帮助你 Esc 之后不煞笔,所以也不算完全没有价值吧…… 12 | 13 | --- 14 | 15 | 我相信很多中文世界的 Vimer 都遇到过这个烦恼,在 vim 的 insert 模式时可能突然想输个中文,输完之后会本能的直接 `esc` 接 normal 模式操作,结果发现跳出来的是中文输入法……对于 vscode,我一般会在几次错误之后被逼到退出 vscode vim 模式,而对于终端中用的 neovim,就只能尽量不输入中文了。 16 | 17 | 为了满足我 1% 用 vim 输入中文的场景(比如写博客),我还是想看看有没有什么解决方案,Google 出来的解决方案基本是:*在退出 insert 模式时记住当时的输入法,并自动切换到默认输入法(一般是英文)给 normal 模式用,并且在下一次进入 insert 模式时再切换回来。* 18 | 19 | 原生 vim 的话,可以使用 [smartim](https://github.com/ybian/smartim) 插件,原理是调用 [im-select](https://github.com/daipeihust/im-select) 这个 CLI 工具来切换输入法。 20 | 21 | 对于 VSCode-vim 的话,smartim 的移植也在近期的 PR 中被 merge 到了插件里,[详情见文档的这部分配置]( https://github.com/VSCodeVim/Vim#use-im-select),需要指定一下默认输入法和 im-select 的 binary 路径就好。 22 | 23 | --- 24 | 25 | 不过实话说,在 vim 中编辑中文的效率和体验和英文比都是大打折扣的。因为中文分词难度太高,不像英文可以简单依靠一个 `split " "` 搞定。所以其实无论 vim(`w`ord,`b`egin,`e`nd),emacs 还是操作系统自带的(比如 macOS 中的 `alt + 箭头`) 「按词移动」功能对于中文都仅仅是跳转到下一个空格处而已,对于中文来说基本就是下一句了……其他常用操作诸如 `f`,`/`, `r`eplace, `t`ill 也都无法很好的工作,基本只能靠 `hjkl` 爬行…… 26 | 27 | 不过也算聊胜于无吧,由于我的主力外置键盘是 HHKB,能用 vim 操作的一个子集(`hjkl`, `o`, `A`, `I`, `v` etc.)可能也比按住 `Fn` 的方向键好用…… 28 | -------------------------------------------------------------------------------- /_posts/2019-09-03-vim-from-finder.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "把「终端下的 Vim」作为 macOS Finder 的打开方式" 4 | subtitle: 'Open file with terminal Vim from the macOS Finder' 5 | author: "Hux" 6 | header-style: text 7 | tags: 8 | - Vim 9 | --- 10 | 11 | 我的日常主力编辑器主要是: 12 | 13 | - (Neo)Vim 14 | - Spacemacs (via Emacs-plus) 15 | - Visual Studio Code 16 | - IntelliJ IDEA 17 | 18 | 这里面只有 (Neo)Vim 是存活在终端中的(我并不在终端内使用 Emacs),而由于我日常主要是从终端(via iTerm)来使用电脑,所以会把他们都加入到 `$PATH` 里以方便从终端中唤起,VSCode 和 IDEA 都有一键加入的功能, Emacs 我在 `~/.zshrc` 中放了一个 `alias emacs='open -n -a Emacs.app .'` 解决。 19 | 20 | 但是,偶尔也会有从 Finder 中打开文件的需求,这时候如果通常会打开拓展名所绑定的 `Open with...` 应用,在大部分时候我的默认绑定是 VSCode,但是今天心血来潮觉得有没有办法直接打开 Vim 呢?搜了一下还真有基于 AppleScript 的解决方案: 21 | 22 | 1. 打开 `Automator.app` 23 | 2. 选择 `New Document` 24 | 3. 找到 `Run AppleScript` 的 action 双击添加 25 | 4. 编写 AppleScript 脚本来唤起终端与 vim (下文给出了我的脚本你可以直接稍作修改使用) 26 | 5. 保存为 `Applications/iTermVim.app` (你可以自己随便取) 27 | 6. 找到你想要以这种方式打开的文件,比如 `<随便>.markdown`,`⌘ i` 获取信息然后修改 `Open with` 为这个应用然后 `Change All...` 28 | 29 | 效果超爽 ;) 30 | 31 | ```applescript 32 | on run {input, parameters} 33 | set filename to POSIX path of input 34 | set cmd to "clear; cd `dirname " & filename & "`;vim " & quote & filename & quote 35 | tell application "iTerm" 36 | activate 37 | tell the current window 38 | create tab with default profile 39 | tell the current session 40 | write text cmd 41 | end tell 42 | end tell 43 | end tell 44 | end run 45 | ``` 46 | 47 | 我这里的代码是采取是用 `iTerm` 与唤起 `vim`、窗口置前、在新窗口中打开、同时 `cd` 到目录。你也可以改成用 macOS 自带的 `Terminal.app`、在新窗口而非新 tab 打开、应用不同的 profile、或是执行其他 executable 等……任你发挥啦。 48 | 49 | ### References 50 | 51 | - [Open file in iTerm vim for MacOS Sierra](https://gist.github.com/charlietran/43639b0f4e0a01c7c20df8f1929b76f2) 52 | - [Open file in Terminal Vim on OSX](https://bl.ocks.org/napcs/2d8376e941133ccfad63e33bf1b1b60c) 53 | -------------------------------------------------------------------------------- /_posts/2019-09-08-spacemacs-workflow.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "My Spacemacs Workflow" 4 | subtitle: 'From Vim to Spacemacs' 5 | author: "Hux" 6 | header-style: text 7 | published: false 8 | tags: 9 | - Vim 10 | - Emacs 11 | --- 12 | 13 | Emacs tend to provide a good support for functional programming languages. Indeed, many FP language community exclusively use Emacs and give only first-party IDE supports to Emacs, such as Coq, Agda, Standard ML, Clojure, etc. 14 | 15 | For the purpose of programming Coq with Proof General, I started to try with Emacs. I quickly found Spacemacs a good alternatives for me...someone had get used to Vim keybindings and want to get some thing useful ASAP w/o configuring a long list as my `.vimrc`. 16 | 17 | Though the overall experience is pretty smooth, many quirks about Spacemacs are always being forgotten and had to look up again and again, so I decided to open a note for some specific "workflow" that I often used. 18 | 19 | Yes this is more like a note publishing online for the purpose of "on-demand accessible". So don't expect good writing anyways. 20 | 21 | 22 | ### Vim-binding 23 | 24 | Choose `evil`! 25 | 26 | 27 | ### Airline 28 | 29 | It's there! 30 | 31 | 32 | ### Nerd Tree / File Sidebar 33 | 34 | `SPC f t` for _file tree_. The keybindings for specific operations are very different w/ Vim NerdTree though. 35 | 36 | 37 | ### Shell / Terminal 38 | 39 | I occasionally use [Neovim's terminal emulator](https://neovim.io/doc/user/nvim_terminal_emulator.html) but in most of the time I just `cmd + D` for iTerms splitted window. 40 | 41 | I even mappped `:D` into split-then-terminal to make the experience on par ;) 42 | 43 | ```vim 44 | command! -nargs=* D belowright split | terminal <args> 45 | ``` 46 | 47 | Anyways, Spacemacs does provide a `:shell` that naturally split a window below for terminal. The experience is not very good though. 48 | 49 | 50 | ### Tabs / Workspaces 51 | 52 | I tend to open multiple _workspace_. Though people might found Vim tabs useful, I am exclusively use iTerm tabs for similar jobs. However Spacemacs is not living in a terminal. 53 | 54 | [r/spacemacs - Vim-style tabs?](https://www.reddit.com/r/spacemacs/comments/5w5d2s/vimstyle_tabs/) gave me a good way to approximate the experience by using [Spacemacs Workspaces](http://spacemacs.org/doc/DOCUMENTATION.html#workspaces): `SPC l w <nth>` trigger a so-called "layout transient state" (I have no idea what's that mean) to open N-th workspaces, and use `gt`/`gT` to switch between. 55 | 56 | 57 | ### Fuzz File Name Search / Rg 58 | 59 | `SPC f f` 60 | 61 | 62 | ### Buffers 63 | 64 | `SPC b b` 65 | -------------------------------------------------------------------------------- /_posts/2019-11-19-is-pwa-dead-in-2019.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "2019 年 PWA(Progressive Web App) 凉了吗?" 4 | subtitle: "Is PWA effectively dead in 2019?" 5 | author: "Hux" 6 | header-style: text 7 | tags: 8 | - 知乎 9 | - Web 10 | - PWA 11 | --- 12 | 13 | > 这篇文章转载自[我在知乎上的回答](https://www.zhihu.com/question/352577624/answer/901867825) 14 | 15 | 作为 PWA 在国内的早期[布道者](https://zhuanlan.zhihu.com/p/25167289)与[实践者](https://zhuanlan.zhihu.com/p/27853228),我觉得挺凉的。 16 | 以下都是主观感受且 opinion is my own。 17 | 18 | **PWA(甚至整个 Web)似乎被 Google(Chrome)与「第三世界」绑到一起去了。**「这世界还有多少人没上过网、没有 4G、没有 3G……印度、印度尼西亚、非洲、乌干达……」这便是这两年的 Chrome Dev Summit 的主旋律了。 19 | 20 | 而这或许也是现在整个 Google 的主旋律吧,于是便成了 Chrome 和 Chrome 的产品经理们的 KPI(OKR),美其名曰「为了互联网的下一个十亿用户」。我不是说关心第三世界这事不好,但问题在于**你一边嘴上说着 「Open Web、大家的 Web」**,**一边身体上却只想着把 Web 变成「你想要的那个 Web」,然后把其他 Web 的发展方向都「耽误」掉了**。 21 | 22 | PWA 的商业案例至今为止,我感到 legit(正当)的仍然只有 twitter,是真正在按一个「给所有用户都能用」的标准来做的。Airbnb/Pinterest/Spotify 可能能及格,而其他的则要么是商业互吹(吹一波走人),要么就是利益(市场导向)一致(Instagram 以及逐年增多的印度系产品)。 23 | 24 | 我相信很多开发者和我一样对 PWA 的期待本来是作为 RN/Flutter 等跨平台开发的 alternatives(替代品),结果现在连几年前的 [hybrid](https://www.zhihu.com/search?q=hybrid&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D) 方案 Cordova (Phonegap)、Electron的实力都没到, 不要说国内各种自家魔改的 Webview(容器、小程序)了。两年的时间本足以做大量这方面的工作 —— 留学前我还担心是不是两年后我就跟不上 PWA 的发展了,结果现在根本就没什么大动静 —— 每年 CDS 确实都仍然会扔几个新的有关 [capability](https://www.zhihu.com/search?q=capability&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D) 的 API 出来, 但是跟了这么多年 Chrome Dev Summit 我也算是看清了这秀场的节奏 —— 每年扔出来的东西吧,第二年弃坑 2/3,剩下 1/3 就是遛狗 —— virtual list 说了几年了?类似 portal 这样的 [navigation-transition](https://www.zhihu.com/search?q=navigation-transition&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D) 说了几年了?file system API 说了几年了?**我吐槽的点在于,Google(Chrome)你年年画大饼,最后大部分有真正投入资源的,全是你那「第三世界」新兴市场相关的。**作为 Web 开发者你一定知道,有多少新 API 落地到我们日常开发了? 25 | 26 | Don't just take my word. 你应该自己去听听这两年的 Chrome Dev Summit,是不是绝大多数的场次都围绕着对「低配」内存、CPU、[网络环境](https://www.zhihu.com/search?q=%E7%BD%91%E7%BB%9C%E7%8E%AF%E5%A2%83&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D)的优化 —— 俨然一副「Web 就只适合在这么不行的地方用」的气息,你一个 Web 开发者都要针对 L1/L2 Cache 优化了你说我们怎么不直接写汇编呢?而单纯谈论 CSS/JS 等 Web 技术的发展,不带使用场景 [bias](https://www.zhihu.com/search?q=bias&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D) 的场次比例一年比一年少。至于 WebAssembly/WebGL/WebXR?—— who TM care? 人家连网都上不了你还想玩 3D/VR 游戏?人家连电脑都没有你还想在 Web 上做生产力工具?WebAssembly 场靠着 Google Research 有点 AI 项目讲了讲 thread 和 SIMD 都能让我感觉到一种与整场会议违和的尴尬……而 3D, VR and AR 总共加起来就做了个六分钟的小短片播,把我乐得。 27 | 28 | 所谓的 Fugu Project(PWA 项目在 Google 的代号)在我眼里就是 Google**「让 Web 成为他们在第三世界的开发平台」**而准备的一个项目:**官方提及 PWA 最爱提的用户场景不是 Web 的可索引性、可链接性、甚至都不是即开即用(on-demand),而是「用户因为没有流量和 wifi 所以不愿安装[原生应用](https://www.zhihu.com/search?q=%E5%8E%9F%E7%94%9F%E5%BA%94%E7%94%A8&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D)」 。**那几个 dev advocate 反正每年就做些 P 用都没有的玩具在那里自娱自乐自 high,做个扫雷游戏然后说我们这个一路支持到**功能机用键盘来玩**哦……一向亲 JSer 的 Addy Osmani 的 Adaptive Loading 场也来一句「我们要为开 **Data Saver(省流量模式、无图模式**)的用户做优化!」,这世界大概是又回去到了 WAP 的时代吧……而项目带头人 Alex Russell,即便我仍然很感激您过去对 Web 的影响和贡献,但您这两年来动不动就是「怼框架怼友商怼空气」—— 你们这些垃圾框架,居然要 50 KB!你们这些垃圾开发者,用什么框架,Use the platform!(i.e. 用我们的 Web Component (的框架)!)你们这些垃圾浏览器,还不快点支持我们要的 API! —— 都是你们伤害了我的 W(K)e(P)b(I)!**司马昭之心,路人皆知**。 29 | 30 | quote [@尤雨溪](//www.zhihu.com/people/cfdec6226ece879d2571fbc274372e9f) 31 | 32 |  33 | 34 | 他们在乎的是「下一个十亿用户」,中国显然不在其中呢 35 | 36 | 37 | 即便你也是 Web 开发者我也是 Web 开发者,但显然我们已经不是 Google(Chrome)想要支持的 Web 开发者了:当无数 Web 开发者起来为 JS 社区在应用框架的先进性上探索,当我们想要证明 Web 在今天的硬件上终于可以挑战 Native,当我们想要在动画和交互上挑战当年的 Flash,当我们认为 Web 技术已经可以胜任众多[桌面软件](https://www.zhihu.com/search?q=%E6%A1%8C%E9%9D%A2%E8%BD%AF%E4%BB%B6&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D),当社区期待 Web 能够积极跟进下一个新兴技术(whatever that is)甚至担当重任,当国人在谈论着 5G 的到来 Web 开发者应该做什么时 —— 这个当年挟 Web 以令 OS,推动 Web 平台 state-of-the-art 的 Google(Chrome)却变得让我不认识了。 38 | 39 | 40 | **Web 自诞生以来便就是个[同床异梦](https://www.zhihu.com/search?q=%E5%90%8C%E5%BA%8A%E5%BC%82%E6%A2%A6&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A901867825%7D)的地方 —— Web 也因此永垂不朽;而对于 PWA 能在当前 Google 的主导下迅速发展成一个有竞争力的跨平台开发解决方案这事儿,或许只是其中的又一黄粱美梦罢了。** 41 | 42 | 43 | 44 | **补充两点:** 45 | 46 | * 我支持「小程序」的产品价值,也支持 PWA 作为 Web 开放标准一部分的技术价值。 47 | * PWA 目前主要靠 Google 推动是客观事实,且 PWA 的发展必须依赖平台(浏览器)的参与。 48 | -------------------------------------------------------------------------------- /_posts/2020-07-05-reflection-2020.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "作为一个前端,看不懂@黄玄 的几乎每一个回答,只有我自己吗?" 4 | subtitle: "Taking this chance to reflect on myself" 5 | author: "Hux" 6 | header-style: text 7 | tags: 8 | - 知乎 9 | - Meta 10 | --- 11 | 12 | > 这篇文章转载自[我在知乎上的回答](https://www.zhihu.com/question/403735935/answer/1321904076) 13 | 14 | 我也看不懂。 15 | ------ 16 | 17 | 对于任何一个我有一定了解的领域,我都知道一大堆我看不懂的东西。反而是对于那些我一点都不了解的,我甚至都说不出来我不懂什么。 18 | 19 | 有的时候我会觉得,在我眼里还只有前端的时候,我还更自信更爱分享一点。可能因为那时候我能感知到的「边界」就只有 2^4 = 16 这么大,还觉得自己满打满算已经懂了 4 吧。打个比喻的话就是觉得自己已经能干活了,但还想再了解下 JS 引擎、浏览器、框架等的工作原理,或许还想再多学点后端和移动端当个全栈?总之 4/16 已经是「全集」的 25% 了,觉得自己还挺棒棒哒。 20 | 21 | 结果等我的「知识」真成长到 16 时,才意识到「欧,原来计算机科学还有这么多东西」?而且每个领域水都深得很,教科书里引论文,论文里再引更多论文,像一棵棵树般不断分形出去…认知的「边界」也相应的长到了 2^16 = 65536。自己懂的东西只占 0.02%,一下觉得自己真是什么都不是了。我把这个瞎掰称之为「认知的指数成长理论」。 22 | 23 | 而我能做的就是学会与这样的认知和平共处。Prof. Matt Might 画的那篇 The illustrated guide to a Ph.D[\[1\]](#ref_1)([「博士是什么」](https://zhuanlan.zhihu.com/p/19789670)) 让我意识到个体在「人类所有知识」面前的渺小,而「成长」的过程,大概就是在那个愈发巨大的「看不懂集」里,挑选出你还愿意继续去「探索」的那些「子集」吧。 24 | 25 |  26 | 27 |  28 | 29 | 「认知的指数成长理论」 30 | 31 | 作为一个前端。 32 | ------- 33 | 34 | 在相当长的一段时间里,「前端」既是我的兴趣也是我的职业,那时好像不需要有区别 —— 从早早在阿里实习,到还没毕业就在微影带团队,小中大的公司都待过,活动也参加了不少。其实如果就这样专注于「作为一个前端」,应该现在也还混得不赖吧。 35 | 36 | 可是偏偏你就发现,那个「看不懂集」的边缘总在发着光 —— 群友形容有一部人的动力在于「理解驱动」,我想了想,那或许是我「半路出家」积累的太多疑惑需要解答;又或许,我可能只是想要「旅游」吧 —— 在高三从重点班理科生转了艺术,在阿里从交互又转了前端,可我还有好奇的理论、又或者还没尝试过系统编程,又或者是下一个有趣的产品形态……想去探索下一件事的欲望总是逐渐盖过了舒适感,你听说了那个学科,你听说了那个文明,你听说了风暴中心,可是你不去看,你就永远不知道那里是什么样。 37 | 38 | 最近多次被问及「前端团队的方向是什么?」才突然意识到自己有一段时间不这样思考了 —— 这个问题天生就带着市场环境强调[精细化分工](https://www.zhihu.com/search?q=%E7%B2%BE%E7%BB%86%E5%8C%96%E5%88%86%E5%B7%A5&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A1321904076%7D)的倾向,而相反地,有时我惊讶于 Facebook 内部「疏于管理」得就像个[开源软件](https://www.zhihu.com/search?q=%E5%BC%80%E6%BA%90%E8%BD%AF%E4%BB%B6&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A1321904076%7D)的菜市场。前端作为一个子领域当然需要特定的技术设施与人员的专长,但或许你我的职业/兴趣发展、公司的组织架构、软件的开发方式,不一定都非得绑上。 39 | 40 | 我想要追求的状态不只是能继续做我已经擅长的事情,我还想去探索那些我想要尝试但可能还不太擅长的事情,最后再顺便把钱赚着 —— 就美其名曰「技术自由」吧。所以你说,我是前端吗,我不是前端吗? 41 | 42 |  43 | 44 |  45 | 46 | 「专注」和「职业」又何必要是一个双射呢? 47 | 48 | 49 | 50 | 回答。 51 | --- 52 | 53 | 答题不是我的工作,我不做培训也不靠这个赚钱,不愿花时间琢磨如何哗众取宠, 54 | 只是有时恰好有新的感悟可以分享,有时恰好有有趣的题目能引发我的思考; 55 | 56 | 答题只是博客之外另一个用写作自我沉淀的地方罢了,难免会有点自我, 57 | 但反正也只是写给同路人看的,也为了发现与认识更多的同路人; 58 | 59 | 我不愿意「只」为了答题而写字,也还是希望言之有物, 60 | 这道题如此 meta,是回答给谁呢,又或是回答给我呢? 61 | 62 | 结语。 63 | --- 64 | 65 | 有的时候需要赚钱,有的时候需要理想。 66 | 你是更想做一位黑客与画家,还是想站在 Hilbert 第十问题的肩上。 67 | 68 | Gödel 说太难,人生又怎会比 Peano 简单。 69 | 面对的 [tradeoff](https://www.zhihu.com/search?q=tradeoff&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A1321904076%7D) 太多,才只能去近似一个想要的模样。 70 | 71 | 说得都是走心的话,走脑还是多看书吧。 72 | 如果能给在读的你带来一点不同思考,那便是对一个碳基生物所能给予的最高嘉奖了。 73 | 74 | 75 | 76 | 黄玄, 77 | 二〇二〇年七月五日, 78 | 于美国[圣塔克拉拉](https://www.zhihu.com/search?q=%E5%9C%A3%E5%A1%94%E5%85%8B%E6%8B%89%E6%8B%89&search_source=Entity&hybrid_search_source=Entity&hybrid_search_extra=%7B%22sourceType%22%3A%22answer%22%2C%22sourceId%22%3A1321904076%7D)。 79 | 80 | 81 | _「有一部分朋友知道,我现在在探索的事情跟前端关系还挺近的啦。_ 82 | _希望我也能突破我自我驱动的局限性,多做一些更落地的事情吧!共勉!」_ 83 | 84 | 参考 85 | -- 86 | 87 | 1. The illustrated guide to a Ph.D [http://matt.might.net/articles/phd-school-in-pictures/](http://matt.might.net/articles/phd-school-in-pictures/) 88 | -------------------------------------------------------------------------------- /_posts/2021-01-19-the-systematic-failure-of-higher-education-in-china.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "中国高等教育的系统性失败" 4 | subtitle: "The Systematic Failure of Higher Education in China" 5 | date: 2021-01-19 12:00:00 6 | author: "Hux" 7 | catalog: false 8 | published: false 9 | header-style: text 10 | tags: 11 | - 被夹 12 | --- 13 | 14 | > 该回答在知乎问题[「如何评价上海交通大学 18 级计算机系第一名「迟先生」的言论?」](https://www.zhihu.com/question/439622084/answer/1685314467) 下无原因被夹。 15 | > 询问我的「专属小管家」多次后仍然给不出任何原因与具体修改意见,自己多次尝试小幅修改无果,干脆直接将原文发上来吧。 16 | 17 | 18 | 高票 [@Youngster38324 的回答](https://www.zhihu.com/question/439622084/answer/1681505518)透露出来的本质上是「**中国高等教育的系统性失败**」,逐层来看: 19 | 20 | 1. 「**进大学前唯分数和同质化教育**」导致了太多人去大学后根本不知道自己要干嘛,很多人专业根本就不是自己选的更不要说知道自己有没有兴趣了,即便是很多高分考生也路径依赖地以为继续努力填鸭就能成功,没有意识到高考后的人生已经换赛道了。这里对比美国高中生的 AP(Advanced Placement)预科制度以及整体社会鼓励向自我发展看而不是向钱看的风气。 21 | 22 | 2. 「**进大学后专业制度没有容错性**」,即便已经发现自己不喜欢被录取专业了也没有办法,因为转专业制度毫无人性(通常要求你先要在你已经不喜欢了的本专业内卷到班级前多少名)。对比美国本科,专业可以 undecided(先上课再决定专业,比如经典的哈佛 CS50,你上下来感兴趣了再去选 CS);学位本身只是某个学科下课程学分累计的自然结果,因此可以灵活的转专业与多学位;班级这种促进内卷的概念被弱化,强调跟自己比关注个人的成长,学生自己控制上几年课,念几个学位,中间休学一下都没关系。 23 | 24 | 3. 前两步的结果就是导致大学为了毕业率把「**评判标准搞成了大锅饭平均主义**」,为了能够每年顺利向社会输送一批(80% 将来都不会从事本专业)的人才,打分根据每年学生情况动态规划自适应,把大学搞成了「严进宽出」。相反美国的大学教育强调「宽进严出」,无论你底子如何,无论重修几次,你只要通过了某个(相对稳定的)客观标准就是合格,为了保证该制度的机械性运作,辅以严格的日常作业计分,对「作弊」零容忍(自动化判重,发现一次重修两次退学)。 25 | 26 | 4. 平均主义进一步导致「**课程设置没有灵活性无法自定义**」,老师不但要照顾及格率还有一颗圣母心希望那些对专业没什么兴趣的人能好歹学到点东西,同时又真心欣赏且想要给予好学的尖子生资源,最后即便绞尽脑汁了也还是只能弄出个在差生里下限高在尖子生里上限低的课程安排两面不当人 —— 尖子生觉得课程要求太低不能激发自己的潜力喂不饱(常见于私下要求加难度或者去无学分旁听),摸鱼的觉得老师影响了我的快乐学习(常见于课堂上一布置作业下面就叫苦连天)该挂还是挂或者 60 分万岁。对比美国,学生的课程表可以自行安排,通常一个课会开多个班次照顾灵活性,学霸可以比别人多上任意节课,也可以跨专业选课或者减少课程增加实习或研究,而且难度自选只要你点过前置技能就行。 27 | 28 | 有类似迟先生这样诉求的人很多,可是一个系统很难由系统内的个体改变,所以很多个体选择了做局部优化趋利避害陪玩成为既得利益者,或者全局优化更换自己所处的系统。 29 | 30 | 只要所处系统里的大部分个体都已经默许了这个游戏规则,无论迟先生是「凡尔赛」还是「理想主义」,改变赛道规则就会被其他个体认为侵害到利益。小孩才分对错,成年人的屁股都是歪得,都是各取所需。 31 | 32 | **都是这个时代的缩影。** 33 | -------------------------------------------------------------------------------- /_posts/2021-04-10-js-20yrs-preface.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: post 3 | title: "《JavaScript 二十年》推荐语" 4 | author: "Hux" 5 | header-style: text 6 | catalog: true 7 | tags: 8 | - Web 9 | - JavaScript 10 | --- 11 | 12 | > 雪碧(doodlewind)邀请我给[《JavaScript 二十年》](https://zhuanlan.zhihu.com/p/373065151) 写的推荐序。 13 | 14 | JavaScript 常常被戏称为一门偶然成功的玩具语言。而实际上,它出身名门,更是成长在聚光灯之下。纵观历史,有资格被标准化的编程语言甚少,它因此成为多方角力的战场,却也有幸同时得到业界与学界先驱的亲传。时至今日,我们甚至难言是它背负了太多妥协,还是这些妥协才成就了它呢。以史为鉴,或许你会有自己的答案。 15 | 16 | — 黄玄,Facebook 软件工程师(编程语言、JS 引擎、前端基础设施)、中文前端社区活跃成员。 17 | -------------------------------------------------------------------------------- /_posts/cs_idols/2019-09-13-peter-john-landin.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Peter John Landin" 3 | subtitle: "「计算机科学偶像」- 彼得·约翰·兰丁" 4 | layout: post 5 | author: "Hux" 6 | published: false 7 | header-style: text 8 | tags: 9 | - CS Idols 10 | --- 11 | 12 | > - [wiki](https://en.wikipedia.org/wiki/Peter_Landin) 13 | > - [维基](https://zh.wikipedia.org/wiki/%E5%BD%BC%E5%BE%97%C2%B7%E5%85%B0%E4%B8%81) 14 | 15 | I was long curious about how does λ calculus become the foundation of formalizaing programming languages. It's strange that I haven't look up the answer until today: It's invented so early by Alonzo Church (whom I will write another post for) as an alternative mathematic foundation in 1930s and its relation with programming language was re-discoverred in 1960s. 16 | 17 | From the "Lambda calculus and programming languages" section of wikipedia page: 18 | 19 | > As pointed out by Peter Landin's 1965 paper "A Correspondence between ALGOL 60 and Church's Lambda-notation" 20 | 21 | I found this name quite familiar since I read his paper "The mechanical evaluation of expressions" before, in which he introduced the first abstract machine for functional programming language, namely [SECD machine](https://en.wikipedia.org/wiki/SECD_machine). This paper also define the term [Closure](https://en.wikipedia.org/wiki/Closure_(computer_programming)) which becomes a prevalent notion in computer programming nowadays. 22 | 23 | Besides of that, his contributions also include: 24 | 25 | - on ALGO definition 26 | - [ISWIM](https://en.wikipedia.org/wiki/ISWIM) programming language 27 | - [off-side rule](https://en.wikipedia.org/wiki/Off-side_rule), known as "indentation-based" syntax nowadays, popularized by Miranda, Haskell, Python, etc. 28 | - coin the term [syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) 29 | 30 | He was much influenced by a study of McCarthy's LISP and taught [Tony Hoare](https://en.wikipedia.org/wiki/Tony_Hoare) ALGO with Peter Naur and Edsger W. Dijkstra. (Oh yes, definitely 4 more people to write). 31 | 32 | I have just download his old, influential paper "The next 700 programming languages". 33 | I am sure it will be an enjoyable read. 34 | -------------------------------------------------------------------------------- /_posts/data_rep/2020-06-21-data-rep-todo.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Data Representation - TODO" 3 | subtitle: "「数据表示」待写" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | published: false 8 | tags: 9 | - 笔记 10 | - 基础 11 | - C 12 | - C++ 13 | --- 14 | 15 | - Endianness 16 | - String (Char Sequence e.g. NULL `0x00`) 17 | - Unicode / UTF8 18 | - Struct and Alignment 19 | - Tagging 20 | - Tagged Pointer 21 | - NaN tagging 22 | - Tagged Integer (SMI) 23 | -------------------------------------------------------------------------------- /_posts/hidden/2020-05-05-pl-chart.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "My Programming Languages Spectrum" 3 | subtitle: "我的编程语言光谱" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | plchart: true 9 | tags: 10 | --- 11 | 12 | <iframe 13 | id="chart" 14 | src="https://huangxuan.me/PL-chart/" 15 | frameborder="0" 16 | scrolling="no" 17 | style="width: 100%"> 18 | </iframe> 19 | -------------------------------------------------------------------------------- /_posts/read_sf_lf/2019-01-02-sf-lf-02-induction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-LC」2 Induction" 3 | subtitle: "Logical Foundations - Proof by Induction" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - LF (逻辑基础) 10 | - SF (软件基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | ## Review (only in slide) 16 | 17 | ```coq 18 | Theorem review2: ∀b, (orb true b) = true. 19 | Theorem review3: ∀b, (orb b true) = true. 20 | ``` 21 | 22 | Whether or not it can be just `simpl.` depending on the definition of `orb`. 23 | 24 | In _Proof Engineering_, we probably won't need to include `review2` but need to include `review3` in library. 25 | 26 | > Why we have `simpl.` but not `refl.` ? 27 | 28 | 29 | Proving `0` is a "neutral element" for `+` (additive identity) 30 | -------------------------------------------------------------- 31 | 32 | ### Proving `0 + n = n` 33 | 34 | ```coq 35 | Theorem plus_O_n : forall n : nat, 0 + n = n. 36 | Proof. 37 | intros n. simpl. reflexivity. Qed. 38 | ``` 39 | 40 | This can be simply proved by _simplication_ bcuz the definition of `+` is defined by pattern matching against 1st operand: 41 | 42 | ```coq 43 | Fixpoint plus (n : nat) (m : nat) : nat := 44 | match n with 45 | | O ⇒ m 46 | | S n' ⇒ S (plus n' m) 47 | end. 48 | ``` 49 | 50 | We can observe that if `n` is `0`(`O`), no matter `m` is, it returns `m` as is. 51 | 52 | 53 | ### Proving `n + 0 = n` 54 | 55 | #### 1st try: Simplication 56 | 57 | ```coq 58 | Theorem plus_O_n_1 : forall n : nat, n + 0 = n. 59 | Proof. 60 | intros n. 61 | simpl. (* Does nothing! *) 62 | Abort. 63 | ``` 64 | 65 | This cannot be proved by _simplication_ bcuz `n` is unknown so _unfold_ the definition `+` won't be able to simplify anything. 66 | 67 | #### 2nd try: Case Analysis 68 | 69 | ```coq 70 | Theorem plus_n_O_2 : ∀n:nat, 71 | n = n + 0. 72 | Proof. 73 | intros n. destruct n as [| n'] eqn:E. 74 | - (* n = 0 *) 75 | reflexivity. (* so far so good... *) 76 | - (* n = S n' *) 77 | simpl. (* ...but here we are stuck again *) 78 | Abort. 79 | ``` 80 | 81 | Our 2nd try is to use _case analysis_ (`destruct`), but the proof stucks in _inductive case_ since `n` can be infinitely large (destructed) 82 | 83 | 84 | #### Induction to the resucue 85 | 86 | > To prove interesting facts about numbers, lists, and other inductively defined sets, we usually need a more powerful reasoning principle: induction. 87 | 88 | Princeple of induction over natural numbers (i.e. _mathematical induction_) 89 | 90 | ```coq 91 | P(0); ∀n' P(n') → P(S n') ====> P(n) 92 | ``` 93 | 94 | In Coq, like `destruct`, `induction` break `P(n)` into 2 subgoals: 95 | 96 | ```coq 97 | Theorem plus_n_O : ∀n:nat, n = n + 0. 98 | Proof. 99 | intros n. induction n as [| n' IHn']. 100 | - (* n = 0 *) reflexivity. 101 | - (* n = S n' *) simpl. rewrite <- IHn'. reflexivity. Qed. 102 | ``` 103 | 104 | 105 | Proving `n - n = 0` 106 | ------------------- 107 | 108 | ```coq 109 | Theorem minus_diag : ∀n, 110 | minus n n = 0. 111 | Proof. 112 | (* WORKED IN CLASS *) 113 | intros n. induction n as [| n' IHn']. 114 | - (* n = 0 *) 115 | simpl. reflexivity. 116 | - (* n = S n' *) 117 | simpl. rewrite → IHn'. reflexivity. Qed 118 | ``` 119 | 120 | Noticed that the definition of `minus`: 121 | 122 | ```coq 123 | Fixpoint minus (n m:nat) : nat := 124 | match n, m with 125 | | O , _ => O 126 | | S _ , O => n 127 | | S n', S m' => minus n' m' 128 | end. 129 | ``` 130 | 131 | `rewrite` 132 | --------- 133 | 134 | `rewrite` would do a (DFS) preorder traversal in the syntax tree. 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /_posts/read_sf_lf/2019-01-13-sf-lf-13-imp-parser.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-LC」13 ImpParser" 3 | subtitle: "Logical Foundations - Lexing And Parsing In Coq" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - LF (逻辑基础) 10 | - SF (软件基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | > the parser relies on some "monadic" programming idioms 16 | 17 | basically, _parser combinator_ (But 非常麻烦 in Coq) 18 | 19 | 20 | Lex 21 | --- 22 | 23 | ```coq 24 | Inductive chartype := white | alpha | digit | other. 25 | 26 | Definition classifyChar (c : ascii) : chartype := 27 | if isWhite c then white 28 | else if isAlpha c then alpha 29 | else if isDigit c then digit 30 | else other. 31 | 32 | 33 | Definition token := string. 34 | ``` 35 | 36 | 37 | 38 | 39 | Syntax 40 | ------ 41 | 42 | 带 error msg 的 `option`: 43 | 44 | ```coq 45 | Inductive optionE (X:Type) : Type := 46 | | SomeE (x : X) 47 | | NoneE (s : string). (** w/ error msg **) 48 | 49 | Arguments SomeE {X}. 50 | Arguments NoneE {X}. 51 | ``` 52 | 53 | 54 | Monadic: 55 | 56 | ```coq 57 | Notation "' p <- e1 ;; e2" 58 | := (match e1 with 59 | | SomeE p ⇒ e2 60 | | NoneE err ⇒ NoneE err 61 | end) 62 | (right associativity, p pattern, at level 60, e1 at next level). 63 | 64 | Notation "'TRY' ' p <- e1 ;; e2 'OR' e3" 65 | := (match e1 with 66 | | SomeE p ⇒ e2 67 | | NoneE _ ⇒ e3 68 | end) 69 | (right associativity, p pattern, 70 | at level 60, e1 at next level, e2 at next level). 71 | ``` 72 | 73 | 74 | ```coq 75 | Definition parser (T : Type) := 76 | list token → optionE (T * list token). 77 | ``` 78 | 79 | ```haskell 80 | newtype Parser a = Parser (String -> [(a,String)]) 81 | 82 | instance Monad Parser where 83 | -- (>>=) :: Parser a -> (a -> Parser b) -> Parser b 84 | p >>= f = P (\inp -> case parse p inp of 85 | [] -> [] 86 | [(v,out)] -> parse (f v) out) 87 | ``` 88 | 89 | 90 | ### combinator `many` 91 | 92 | Coq vs. Haskell 93 | 1. explicit recursion depth, .e. _step-indexed_ 94 | 2. explicit exception `optionE` (in Haskell, it's hidden behind the `Parser` Monad as `[]`) 95 | 3. explicit string state `xs` (in Haskell, it's hidden behind the `Parser` Monad as `String -> String`) 96 | 4. explicit `acc`epted token (in Haskell, it's hidden behind the `Parser` Monad as `a`, argument) 97 | 98 | ```coq 99 | Fixpoint many_helper {T} (p : parser T) acc steps xs := 100 | match steps, p xs with 101 | | 0, _ ⇒ 102 | NoneE "Too many recursive calls" 103 | | _, NoneE _ ⇒ 104 | SomeE ((rev acc), xs) 105 | | S steps', SomeE (t, xs') ⇒ 106 | many_helper p (t :: acc) steps' xs' 107 | end. 108 | 109 | Fixpoint many {T} (p : parser T) (steps : nat) : parser (list T) := 110 | many_helper p [] steps. 111 | ``` 112 | 113 | ```haskell 114 | manyL :: Parser a -> Parser [a] 115 | manyL p = many1L p <++ return [] -- left biased OR 116 | 117 | many1L :: Parser a -> Parser [a] 118 | many1L p = (:) <gt; p <*> manyL p 119 | -- or 120 | many1L p = do x <- p 121 | xs <- manyL p 122 | return (x : xs) 123 | ``` 124 | 125 | 126 | ### `ident` 127 | 128 | 129 | ```coq 130 | Definition parseIdentifier (xs : list token) : optionE (string * list token) := 131 | match xs with 132 | | [] ⇒ NoneE "Expected identifier" 133 | | x::xs' ⇒ if forallb isLowerAlpha (list_of_string x) 134 | then SomeE (x, xs') 135 | else NoneE ("Illegal identifier:'" ++ x ++ "'") 136 | end. 137 | ``` 138 | 139 | ```haskell 140 | ident :: Parser String 141 | ident = do x <- lower 142 | xs <- many alphanum 143 | return (x:xs) 144 | ``` 145 | -------------------------------------------------------------------------------- /_posts/read_sf_lf/2019-01-14-sf-lf-14-imp-ceval.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-LC」14 ImpCEvalFun" 3 | subtitle: "Logical Foundations - An Evaluation Function For Imp" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - LF (逻辑基础) 10 | - SF (软件基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | 16 | Step-Indexed Evaluator 17 | ---------------------- 18 | 19 | ...Copied from `12-imp.md`: 20 | 21 | > Chapter `ImpCEvalFun` provide some workarounds to make functional evalution works: 22 | > 1. _step-indexed evaluator_, i.e. limit the recursion depth. (think about _Depth-Limited Search_). 23 | > 2. return `option` to tell if it's a normal or abnormal termination. 24 | > 3. use `LETOPT...IN...` to reduce the "optional unwrapping" (basicaly Monadic binding `>>=`!) 25 | > this approach of `let-binding` became so popular in ML family. 26 | 27 | 28 | ```coq 29 | Notation "'LETOPT' x <== e1 'IN' e2" 30 | := (match e1 with 31 | | Some x ⇒ e2 32 | | None ⇒ None 33 | end) 34 | (right associativity, at level 60). 35 | 36 | Open Scope imp_scope. 37 | Fixpoint ceval_step (st : state) (c : com) (i : nat) 38 | : option state := 39 | match i with 40 | | O ⇒ None (* depth-limit hit! *) 41 | | S i' ⇒ 42 | match c with 43 | | SKIP ⇒ 44 | Some st 45 | | l ::= a1 ⇒ 46 | Some (l !-> aeval st a1 ; st) 47 | | c1 ;; c2 ⇒ 48 | LETOPT st' <== ceval_step st c1 i' IN (* option bind *) 49 | ceval_step st' c2 i' 50 | | TEST b THEN c1 ELSE c2 FI ⇒ 51 | if (beval st b) 52 | then ceval_step st c1 i' 53 | else ceval_step st c2 i' 54 | | WHILE b1 DO c1 END ⇒ 55 | if (beval st b1) 56 | then LETOPT st' <== ceval_step st c1 i' IN 57 | ceval_step st' c i' 58 | else Some st 59 | end 60 | end. 61 | Close Scope imp_scope. 62 | ``` 63 | 64 | 65 | 66 | Relational vs. Step-Indexed Evaluation 67 | -------------------------------------- 68 | 69 | Prove `ceval_step` is equiv to `ceval` 70 | 71 | 72 | ### -> 73 | 74 | ```coq 75 | Theorem ceval_step__ceval: forall c st st', 76 | (exists i, ceval_step st c i = Some st') -> 77 | st =[ c ]=> st'. 78 | ``` 79 | 80 | The critical part of proof: 81 | 82 | - `destruct` for the `i`. 83 | - `induction i`, generalize on all `st st' c`. 84 | 1. `i = 0` case contradiction 85 | 2. `i = S i'` case; 86 | `destruct c`. 87 | - `destruct (ceval_step ...)` for the `option` 88 | 1. `None` case contradiction 89 | 2. `Some` case, use induction hypothesis... 90 | 91 | 92 | ### <- 93 | 94 | ```coq 95 | Theorem ceval__ceval_step: forall c st st', 96 | st =[ c ]=> st' -> 97 | exists i, ceval_step st c i = Some st'. 98 | Proof. 99 | intros c st st' Hce. 100 | induction Hce. 101 | ``` 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /_posts/read_sf_lf/2019-01-15-sf-lf-15-extraction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-LC」15 Extraction" 3 | subtitle: "Logical Foundations - Extracting ML From Coq" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - LF (逻辑基础) 10 | - SF (软件基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | 16 | Basic Extraction 17 | ---------------- 18 | 19 | - OCaml (most mature) 20 | - Haskell (mostly works) 21 | - Scheme (a bit out of date) 22 | 23 | ```coq 24 | Extraction "imp1.ml" ceval_step. 25 | ``` 26 | 27 | When Coq processes this command: 28 | 29 | ``` 30 | The file imp1.ml has been created by extraction. 31 | The file imp1.mli has been created by extraction. 32 | ``` 33 | 34 | 35 | 36 | Controlling Extraction of Specific Types 37 | ---------------------------------------- 38 | 39 | 如果不做任何处理的话...生成的 `ml` 里的 `nat` 则都会是 Church Numeral... 40 | 41 | > We can tell Coq how to extract certain `Inductive` definitions to specific OCaml types. 42 | > we must say: 43 | > 1. how the Coq type itself should be represented in OCaml 44 | > 2. how each constructor should be translated 45 | 46 | ```coq 47 | Extract Inductive bool ⇒ "bool" [ "true" "false" ]. 48 | ``` 49 | 50 | > also, for non-enumeration types (where the constructors take arguments), 51 | > we give an OCaml expression that can be used as a _"recursor"_ over elements of the type. (Think Church numerals.) 52 | 53 | ```coq 54 | Extract Inductive nat ⇒ "int" 55 | [ "0" "(fun x → x + 1)" ] 56 | "(fun zero succ n → 57 | if n=0 then zero () else succ (n-1))". 58 | ``` 59 | 60 | ```coq 61 | Extract Constant plus ⇒ "( + )". 62 | Extract Constant mult ⇒ "( * )". 63 | Extract Constant eqb ⇒ "( = )". 64 | ``` 65 | 66 | > 注意:保证提取结果的合理性是你的责任。 67 | 68 | ```coq 69 | Extract Constant minus ⇒ "( - )". 70 | ``` 71 | 72 | 比如这么做很诱人……但是我们 Coq 的定义里 `0 - 1 = 0`, OCaml 的 `int` 则会有负数... 73 | 74 | 75 | 76 | ### Recursor 的理论与实现 - a "encoding" of case expression and sum type 77 | 78 | ```coq 79 | Fixpoint ceval_step (st : state) (c : com) (i : nat) 80 | : option state := 81 | match i with 82 | | O => None 83 | | S i' => 84 | match c with 85 | ``` 86 | ```ocaml 87 | let rec ceval_step st c = function 88 | | O -> None 89 | | S i' -> 90 | (match c with 91 | ``` 92 | ```ocaml 93 | let rec ceval_step st c i = 94 | (fun zero succ n -> if n=0 then zero () else succ (n-1)) 95 | (fun _ -> None) (* zero *) 96 | (fun i' -> (* succ *) 97 | match c with 98 | ``` 99 | 100 | 注意我们是如何使用 "recursor" 来替代 `case`, `match`, pattern matching 得。 101 | 102 | recall _sum type_ 在 PLT 中的语法与语义: 103 | 104 | ```coq 105 | T ::= 106 | T + T 107 | 108 | e ::= 109 | case e of 110 | | L(e) => e 111 | | R(e) => e 112 | 113 | ``` 114 | ``` 115 | e → e' 116 | ------------- (work inside constructor) 117 | C(e) -> C(e') 118 | 119 | e → e' 120 | ------------------------------- (work on the expr match against) 121 | case e of ... → case e' of ... 122 | 123 | ----------------------------------------------- (match Left constructor, substitute) 124 | case L(v) of L(x) => e1 | R(y) => e2 → e1 [v/x] 125 | 126 | ----------------------------------------------- (match Right constructor, substitute) 127 | case R(v) of L(x) => e1 | R(y) => e2 → e1 [v/x] 128 | ``` 129 | 130 | 可以发现 `case` 表达式可以理解为一种特殊的 application,会将其 argument 根据某种 tag (这里为构造函数) apply 到对应的 case body 上, 131 | 每个 case body 都是和 lambda abstraction 同构的一种 binder: 132 | 133 | L(x) => e1 === λx.e1 134 | R(x) => e2 === λx.e2 135 | 136 | case v e1|e2 === (λx.e1|e2) v -- `e1` or `e2` depends on the _tag_ wrapped on `v` 137 | 138 | 这个角度也解释了 Haskell/SML 在申明函数时直接对参数写 pattern match 的理论合理性. 139 | 140 | 根据经验几乎所有的 _binding_ 都可以被 desugar 成函数(即 lambda expression). 141 | 难点在于我们如何 re-implement 这个 _tag_ 的 _switch_ 机制? 142 | 143 | 对于 `Inductive nat` 翻译到 OCaml `int` 时,这个机制可以用 `v =? 0` 来判断,因此我们的 _recursor_ 实现为 144 | 145 | ```ocaml 146 | fun zero succ (* partial application *) 147 | n -> if n=0 (* 判断 tag ... *) 148 | then zero () (* 0 case => (λx.e1) v *) 149 | else succ (n-1) (* S n case => (λx.e2) v *) 150 | ``` 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-02-sf-plf-02-hoare-1.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」2 Hoare" 3 | subtitle: "Programming Language Foundations - Hoare Logic, Part I " 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | TBD 16 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-03-sf-plf-03-hoare-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」3 Hoare2" 3 | subtitle: "Programming Language Foundations - Hoare Logic, Part II" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | TBD 16 | 17 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-04-sf-plf-04-hoare-logic.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」4 HoareAsLogic" 3 | subtitle: "Programming Language Foundations - Hoare Logic as a Logic" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | TBD 16 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-10-sf-plf-10-subtyping.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」10 Sub" 3 | subtitle: "Programming Language Foundations - Subtyping (子类型化)" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | 16 | 17 | Concepts 18 | -------- 19 | 20 | 21 | 22 | ### The Subsumption Rule 23 | 24 | 25 | ### The Subtype Relation 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | ### Slide QA1 41 | 42 | Record Subtyping... 43 | 44 | row type 45 | 46 | 47 | index? record impl as list 48 | 49 | 50 | width/depth/permulation 51 | - multiple step rules 52 | 53 | 54 | 55 | --- 56 | 57 | 58 | Java 59 | 60 | 1. class - no index (thinking about offset) 61 | 62 | having both width/permulation subtyping make impl slow 63 | - OOP - hmm 64 | - ML has no permulation - for perf reason (static structure) as C 65 | 66 | ML has depth? 67 | - a little bit by equality 68 | 69 | 70 | OCaml objection has all three 71 | 72 | 73 | ### Slide QA2 74 | 75 | Looking at Contravariant! 76 | 77 | 1. (2) `{i1:S,i2:T}→U <: {i1:S,i2:T,i3:V}→U` 78 | 79 | 2. (4) `{i1:T,i2:V,i3:V} <: {i1:S,i2:U} * {i3:V}` is interesting: 80 | 81 | the interesting thing is, why don't we make some subtyping rules for that as well? 82 | 83 | - there are definitely _code_ can do that 84 | - their _runtime_ semantics are different tho they carry same information 85 | - __coercion__ can used for that 86 | 87 | 3 and 4. (5) ... 88 | 89 | 90 | A <: Top => Top -> A <: A -> A -- contravariant 91 | 92 | if we only care `(A*T)`, can use `T:Top` 93 | 94 | but to type the whole thing `: A` 95 | 96 | `Top -> A`? 97 | but noticed that we said `\z:A.z` 98 | 99 | can we pass `A -> A` into `Top -> A`? 100 | more specific more general 101 | 102 | smallest -> most specific -> `A -> A` 103 | largest -> most specific -> `Top -> A` 104 | 105 | 106 | 5. 107 | "The type Bool has no proper subtypes." (I.e., the only type smaller than Bool is Bool itself.) 108 | Ture unless we have Bottom 109 | 110 | hmm seems like `Bottom` in subtyping is different with Empty/Void, which is closer to logical `Bottom ⊥` since Bottom here is subtyping of everything.. 111 | OH they are the same: (nice) 112 | > <https://en.wikipedia.org/wiki/Bottom_type> 113 | 114 | 6. True 115 | 116 | 117 | 118 | ### Inversion Lemmas for Subtyping 119 | 120 | `inversion` doesn't lose information, `induction` does. 121 | 122 | auto rememeber?? --- dependent induction 123 | hetergeous equaltiy 124 | 125 | 126 | 127 | In soundness proof 128 | 129 | - subtyping only affects Canonical Forms + T_Sub case in induction 130 | 131 | 132 | > Lemma: If Gamma ⊢ \x:S1.t2 ∈ T, then there is a type S2 such that x⊢>S1; Gamma ⊢ t2 ∈ S2 and S1 → S2 <: T. 133 | 134 | why `T` not arrow? Top... 135 | 136 | 137 | if including Bottom...many proof becomes hard, canonical form need to say...might be Bottom? 138 | 139 | > no, no value has type Bottom (Void)... 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-12-sf-plf-12-records.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」12 Records" 3 | subtitle: "Programming Language Foundations - Adding Records To STLC" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | 16 | ## Adding Records 17 | 18 | 19 | ```coq 20 | t ::= Terms: 21 | | {i1=t1, ..., in=tn} record 22 | | t.i projection 23 | | ... 24 | 25 | v ::= Values: 26 | | {i1=v1, ..., in=vn} record value 27 | | ... 28 | 29 | T ::= Types: 30 | | {i1:T1, ..., in:Tn} record type 31 | | ... 32 | ``` 33 | 34 | 35 | ## Formalizing Records 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-14-sf-plf-14-record-sub.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」14 RecordSub" 3 | subtitle: "Programming Language Foundations - Subtyping with Records" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | 16 | ```coq 17 | Inductive ty : Type := 18 | (* record types *) 19 | | RNil : ty 20 | | RCons : string → ty → ty → ty. 21 | ``` 22 | 23 | we need typecon to identify record... 24 | 25 | 26 | ```coq 27 | Inductive tm : Type := 28 | | rproj ...? isn't it as well? 29 | (* record terms *) 30 | | rnil : tm 31 | | rcons : string → tm → tm → tm. 32 | `` 33 | 34 | as a list... 35 | 36 | 37 | for Record, can compiler reorder the fields? (SML and OCaml) 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-15-sf-plf-15-norm-STLC.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」15 Norm" 3 | subtitle: "Programming Language Foundations - Normalization of STLC" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | TBD 16 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-16-sf-plf-16-lib-tactics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」16 LibTactics" 3 | subtitle: "Programming Language Foundations - A Collection of Handy General-Purpose Tactics" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | TBD 16 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-17-sf-plf-17-use-tactics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」17 UseTactics" 3 | subtitle: "Programming Language Foundations - Tactic Library For Coq" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | ```coq 16 | From PLF Require Import LibTactics. 17 | ``` 18 | 19 | `LibTactics` vs. `SSReflect` (another tactics package) 20 | 21 | - for PL vs. for math 22 | - traditional vs. rethinks..so harder 23 | 24 | 25 | Tactics for Naming and Performing Inversion 26 | ------------------------------------------- 27 | 28 | ### `introv` 29 | 30 | ```coq 31 | Theorem ceval_deterministic: ∀c st st1 st2, 32 | st =[ c ]⇒ st1 → 33 | st =[ c ]⇒ st2 → 34 | st1 = st2. 35 | intros c st st1 st2 E1 E2. (* 以往如果想给 Hypo 命名必须说全 *) 36 | introv E1 E2. (* 现在可以忽略 forall 的部分 *) 37 | ``` 38 | 39 | ### `inverts` 40 | 41 | ```coq 42 | (* was... 需要 subst, clear *) 43 | - inversion H. subst. inversion H2. subst. 44 | (* now... *) 45 | - inverts H. inverts H2. 46 | 47 | 48 | (* 可以把 invert 出来的东西放在 goal 的位置让你自己用 intro 命名!*) 49 | inverts E2 as. 50 | ``` 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | Tactics for N-ary Connectives 59 | ----------------------------- 60 | 61 | > Because Coq encodes conjunctions and disjunctions using binary constructors ∧ and ∨... 62 | > to work with a `N`-ary logical connectives... 63 | 64 | ### `splits` 65 | 66 | > n-ary conjunction 67 | 68 | n-ary `split` 69 | 70 | 71 | ### `branch` 72 | 73 | > n-ary disjunction 74 | 75 | faster `destruct`? 76 | 77 | 78 | 79 | 80 | 81 | 82 | Tactics for Working with Equality 83 | --------------------------------- 84 | 85 | 86 | ### `asserts_rewrite` and `cuts_rewrite` 87 | 88 | 89 | ### `substs` 90 | 91 | better `subst` - not fail on circular eq 92 | 93 | 94 | ### `fequals` 95 | 96 | vs `f_equal`? 97 | 98 | 99 | ### `applys_eq` 100 | 101 | variant of `eapply` 102 | 103 | 104 | 105 | 106 | 107 | Some Convenient Shorthands 108 | -------------------------- 109 | 110 | 111 | ### `unfolds` 112 | 113 | better `unfold` 114 | 115 | 116 | ### `false` and `tryfalse` 117 | 118 | better `exfalso` 119 | 120 | 121 | ### `gen` 122 | 123 | shorthand for `generalize dependent`, multiple arg. 124 | 125 | ```coq 126 | (* old *) 127 | intros Gamma x U v t S Htypt Htypv. 128 | generalize dependent S. generalize dependent Gamma. 129 | 130 | (* new...so nice!!! *) 131 | introv Htypt Htypv. gen S Gamma. 132 | ``` 133 | 134 | 135 | ### `admits`, `admit_rewrite` and `admit_goal` 136 | 137 | wrappers around `admit` 138 | 139 | 140 | ### `sort` 141 | 142 | > proof context more readable 143 | 144 | vars -> top 145 | hypotheses -> bottom 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | Tactics for Advanced Lemma Instantiation 154 | ---------------------------------------- 155 | 156 | 157 | ### Working on `lets` 158 | 159 | ### Working on `applys`, `forwards` and `specializes` 160 | 161 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-18-sf-plf-18-use-auto.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」18 UseAuto" 3 | subtitle: "Programming Language Foundations - Theory And Practice Of Automation In Coq Proofs" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | 16 | 17 | ## Basic Features of Proof Search 18 | 19 | ### Strength of Proof Search 20 | 21 | > four proof-search tactics: `auto`, `eauto`, `iauto` and `jauto`. 22 | 23 | 24 | 25 | 26 | --- 27 | 28 | 29 | ## How Proof Search Works 30 | 31 | ### Search Depth 32 | 33 | ### Backtracking 34 | 35 | ### Adding Hints 36 | 37 | ### Integration of Automation in Tactics 38 | 39 | 40 | 41 | --- 42 | 43 | 44 | 45 | ## Example Proofs 46 | 47 | 48 | 49 | --- 50 | 51 | 52 | 53 | ## Advanced Topics in Proof Search 54 | 55 | 56 | ### 57 | 58 | 59 | --- 60 | 61 | 62 | ## Decision Procedures 63 | 64 | 65 | ### Omega 66 | 67 | ### Ring 68 | 69 | ### Congurence 70 | 71 | -------------------------------------------------------------------------------- /_posts/read_sf_plf/2019-03-19-sf-plf-19-partial-eval.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "「SF-PLF」19 PE" 3 | subtitle: "Programming Language Foundations - Partial Evaluation" 4 | layout: post 5 | author: "Hux" 6 | header-style: text 7 | hidden: true 8 | tags: 9 | - SF (软件基础) 10 | - PLF (编程语言基础) 11 | - Coq 12 | - 笔记 13 | --- 14 | 15 | TBD 16 | -------------------------------------------------------------------------------- /about.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: "About" 4 | description: "「他单纯只想把日子过得不浪费」" 5 | header-img: "img/bg-me-2022.jpg" 6 | header-mask: 0.3 7 | multilingual: true 8 | --- 9 | 10 | {% include multilingual-sel.html %} 11 | 12 | <!-- Chinese Version --> 13 | <div class="zh post-container"> 14 | {% capture about_zh %}{% include about/zh.md %}{% endcapture %} 15 | {{ about_zh | markdownify }} 16 | </div> 17 | 18 | <!-- English Version --> 19 | <div class="en post-container"> 20 | {% capture about_en %}{% include about/en.md %}{% endcapture %} 21 | {{ about_en | markdownify }} 22 | </div> 23 | 24 | 25 | {% if site.disqus_username %} 26 | <!-- disqus 评论框 start --> 27 | <div class="comment"> 28 | <div id="disqus_thread" class="disqus-thread"> 29 | 30 | </div> 31 | </div> 32 | <!-- disqus 评论框 end --> 33 | 34 | <!-- disqus 公共JS代码 start (一个网页只需插入一次) --> 35 | <script type="text/javascript"> 36 | /* * * CONFIGURATION VARIABLES * * */ 37 | var disqus_shortname = "{{site.disqus_username}}"; 38 | var disqus_identifier = "{{site.disqus_username}}/{{page.url}}"; 39 | var disqus_url = "{{site.url}}{{page.url}}"; 40 | 41 | (function () { 42 | var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true; 43 | dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js'; 44 | (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq); 45 | })(); 46 | </script> 47 | <!-- disqus 公共JS代码 end --> 48 | {% endif %} 49 | -------------------------------------------------------------------------------- /ads.txt: -------------------------------------------------------------------------------- 1 | google.com, pub-6487568398225121, DIRECT, f08c47fec0942fa0 -------------------------------------------------------------------------------- /archive.html: -------------------------------------------------------------------------------- 1 | --- 2 | title: Archive 3 | layout: default 4 | description: "「我干了什么 究竟拿了时间换了什么」" 5 | header-img: "img/bg-little-universe.jpg" 6 | --- 7 | 8 | <!-- 9 | Credits: this page shamelessly borrowed a lot from: 10 | https://github.com/kitian616/jekyll-TeXt-theme 11 | --> 12 | <!-- Page Header --> 13 | {% include intro-header.html type='page' short=true %} 14 | 15 | <!-- Main Content --> 16 | <div class="container"> 17 | <div class="row"> 18 | <div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1"> 19 | <!-- Tags (as filter) --> 20 | <div id='tag_cloud' class="tags tags-sup js-tags"> 21 | <a class="tag-button--all" data-encode=""> 22 | Show All 23 | <sup>{{site.posts.size}}</sup> 24 | </a> 25 | 26 | {% capture tags %} 27 | {% for tag in site.tags %} 28 | <a data-sort="{{ site.posts.size | minus: tag[1].size | prepend: '0000' | slice: -4, 4 }}" 29 | data-encode="{{ tag[0] | strip | url_encode }}" class="tag-button" title="{{ tag[0] }}" 30 | rel="{{ tag[1].size }}"> 31 | {{ tag[0] }} 32 | <sup>{{tag[1].size}}</sup> 33 | </a>__SEPERATOR__ 34 | {% endfor %} 35 | {% endcapture %} 36 | {{ tags | split:'__SEPERATOR__' | sort }} 37 | </div> 38 | 39 | <!-- Article List --> 40 | <div class="mini-post-list js-result d-none"> 41 | {%- assign _sorted_list = site.posts -%} 42 | {%- assign _sorted_list = _sorted_list | sort: 'date' -%} 43 | {%- assign _sorted_list = _sorted_list | reverse -%} 44 | 45 | 46 | {%- for _article in _sorted_list -%} 47 | {%- assign _tags = '' -%} 48 | {%- for _tag in _article.tags -%} 49 | {%- assign _tag_encode = _tag | strip | url_encode -%} 50 | {%- if forloop.last -%} 51 | {%- assign _tags = _tags | append: _tag_encode -%} 52 | {%- else -%} 53 | {%- assign _tags = _tags | append: _tag_encode | append: ',' -%} 54 | {%- endif -%} 55 | {%- endfor -%} 56 | 57 | {% comment %} group by year {% endcomment %} 58 | {%- assign _currentdate = _article.date | date: '%Y' -%} 59 | {%- if _currentdate != _date -%} 60 | {%- unless forloop.first -%}</section>{%- endunless -%} 61 | <section> 62 | <span class="fa listing-seperator"> 63 | <span class="tag-text">{{ _currentdate }}</span> 64 | </span> 65 | {%- assign _date = _currentdate -%} 66 | {%- endif -%} 67 | 68 | <div class="post-preview item" data-tags="{{ _tags }}"> 69 | <a href="{{ _article.url | prepend: site.baseurl }}"> 70 | <h2 class="post-title"> 71 | {{ _article.title }} 72 | </h2> 73 | {% if _article.subtitle %} 74 | <h3 class="post-subtitle"> 75 | {{ _article.subtitle }} 76 | </h3> 77 | {% endif %} 78 | </a> 79 | <hr> 80 | </div> 81 | {%- if forloop.last -%} 82 | </section>{%- endif -%} 83 | {% endfor %} 84 | </div> 85 | </div> 86 | </div> 87 | </div> 88 | -------------------------------------------------------------------------------- /feed.xml: -------------------------------------------------------------------------------- 1 | --- 2 | layout: null 3 | --- 4 | <?xml version="1.0" encoding="UTF-8"?> 5 | <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> 6 | <channel> 7 | <title>{{ site.title | xml_escape }}</title> 8 | <description>{{ site.description | xml_escape }}</description> 9 | <link>{{ site.url }}{{ site.baseurl }}/</link> 10 | <atom:link href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" rel="self" type="application/rss+xml" /> 11 | <pubDate>{{ site.time | date_to_rfc822 }}</pubDate> 12 | <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate> 13 | <generator>Jekyll v{{ jekyll.version }}</generator> 14 | {% for post in site.posts limit:10 %} 15 | <item> 16 | <title>{{ post.title | xml_escape }}</title> 17 | <description>{{ post.content | xml_escape }}</description> 18 | <pubDate>{{ post.date | date_to_rfc822 }}</pubDate> 19 | <link>{{ post.url | prepend: site.baseurl | prepend: site.url }}</link> 20 | <guid isPermaLink="true">{{ post.url | prepend: site.baseurl | prepend: site.url }}</guid> 21 | {% for tag in post.tags %} 22 | <category>{{ tag | xml_escape }}</category> 23 | {% endfor %} 24 | {% for cat in post.categories %} 25 | <category>{{ cat | xml_escape }}</category> 26 | {% endfor %} 27 | </item> 28 | {% endfor %} 29 | </channel> 30 | </rss> 31 | -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /img/404-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/404-bg.jpg -------------------------------------------------------------------------------- /img/avatar-hux-home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/avatar-hux-home.jpg -------------------------------------------------------------------------------- /img/avatar-hux-ny.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/avatar-hux-ny.jpg -------------------------------------------------------------------------------- /img/avatar-hux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/avatar-hux.jpg -------------------------------------------------------------------------------- /img/bg-little-universe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/bg-little-universe.jpg -------------------------------------------------------------------------------- /img/bg-material.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/bg-material.jpg -------------------------------------------------------------------------------- /img/bg-me-2022.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/bg-me-2022.jpg -------------------------------------------------------------------------------- /img/bg-walle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/bg-walle.jpg -------------------------------------------------------------------------------- /img/blog-desktop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/blog-desktop.jpg -------------------------------------------------------------------------------- /img/blog-keynote.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/blog-keynote.jpg -------------------------------------------------------------------------------- /img/blog-md-navbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/blog-md-navbar.gif -------------------------------------------------------------------------------- /img/blog-sidebar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/blog-sidebar.jpg -------------------------------------------------------------------------------- /img/contact-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/contact-bg.jpg -------------------------------------------------------------------------------- /img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/favicon.ico -------------------------------------------------------------------------------- /img/home-bg-art.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/home-bg-art.jpg -------------------------------------------------------------------------------- /img/home-bg-geek.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/home-bg-geek.jpg -------------------------------------------------------------------------------- /img/home-bg-o.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/home-bg-o.jpg -------------------------------------------------------------------------------- /img/home-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/home-bg.jpg -------------------------------------------------------------------------------- /img/icon_wechat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/icon_wechat.png -------------------------------------------------------------------------------- /img/in-post/forcify.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/forcify.jpg -------------------------------------------------------------------------------- /img/in-post/open-source-license.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/open-source-license.png -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.013.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.013.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.014.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.014.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.016.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.016.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.018.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.018.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.019.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.019.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.020.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.020.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.021.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.021.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.023.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.023.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.026.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.026.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.028.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.028.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.029.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.029.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.030.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.030.jpg -------------------------------------------------------------------------------- /img/in-post/post-alitrip-pd/post-alitrip-pd.031.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-alitrip-pd/post-alitrip-pd.031.jpg -------------------------------------------------------------------------------- /img/in-post/post-c-u-ali-079717.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-c-u-ali-079717.png -------------------------------------------------------------------------------- /img/in-post/post-c-u-ali-memo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-c-u-ali-memo.jpg -------------------------------------------------------------------------------- /img/in-post/post-c-u-ali-team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-c-u-ali-team.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/Architecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/Architecture.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/Lighthouse-after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/Lighthouse-after.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/Lighthouse-before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/Lighthouse-before.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/PRECACHE-future-routes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/PRECACHE-future-routes.jpg -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/PUSH-link-rel-preload.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/PUSH-link-rel-preload.jpg -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/after-skeleton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/after-skeleton.jpg -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/before-skeleton.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/before-skeleton.jpg -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/eleme-at-io.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/eleme-at-io.jpg -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/msite-After-Optim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/msite-After-Optim.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/msite-Before-Optim.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/msite-Before-Optim.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/nextTick-&-Load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/nextTick-&-Load.png -------------------------------------------------------------------------------- /img/in-post/post-eleme-pwa/thisTick-&-Load.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-eleme-pwa/thisTick-&-Load.png -------------------------------------------------------------------------------- /img/in-post/post-f-f-weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-f-f-weibo.png -------------------------------------------------------------------------------- /img/in-post/post-js-version/javascript-java.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-js-version/javascript-java.jpg -------------------------------------------------------------------------------- /img/in-post/post-js-version/keep-calm-and-learn-javascript.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-js-version/keep-calm-and-learn-javascript.png -------------------------------------------------------------------------------- /img/in-post/post-kuaidi-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-kuaidi-1.jpg -------------------------------------------------------------------------------- /img/in-post/post-kuaidi-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-kuaidi-2.jpg -------------------------------------------------------------------------------- /img/in-post/post-metro-panorama.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-metro-panorama.jpg -------------------------------------------------------------------------------- /img/in-post/post-metro-real.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-metro-real.jpg -------------------------------------------------------------------------------- /img/in-post/post-metro-ui.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-metro-ui.jpg -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/PWAR-007.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/PWAR-007.jpeg -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/PWAR-014+PWA.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/PWAR-014+PWA.jpeg -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/flipkart-1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/flipkart-1.jpeg -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/flipkart-2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/flipkart-2.jpeg -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/flipkart-3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/flipkart-3.jpeg -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/ios2-a2hs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/ios2-a2hs.gif -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/qcon-hybridzation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/qcon-hybridzation.png -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/qcon-trend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/qcon-trend.png -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/sw-lifecycle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/sw-lifecycle.png -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/sw-race.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/sw-race.png -------------------------------------------------------------------------------- /img/in-post/post-nextgen-web-pwa/sw-sw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-nextgen-web-pwa/sw-sw.png -------------------------------------------------------------------------------- /img/in-post/post-wmu/maoyan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-wmu/maoyan.jpg -------------------------------------------------------------------------------- /img/in-post/post-wmu/question.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-wmu/question.jpg -------------------------------------------------------------------------------- /img/in-post/post-wmu/wepiao.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/in-post/post-wmu/wepiao.jpg -------------------------------------------------------------------------------- /img/post-bg-2015.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-2015.jpg -------------------------------------------------------------------------------- /img/post-bg-alibaba.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-alibaba.jpg -------------------------------------------------------------------------------- /img/post-bg-alitrip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-alitrip.jpg -------------------------------------------------------------------------------- /img/post-bg-android.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-android.jpg -------------------------------------------------------------------------------- /img/post-bg-apple-event-2015.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-apple-event-2015.jpg -------------------------------------------------------------------------------- /img/post-bg-css.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-css.jpg -------------------------------------------------------------------------------- /img/post-bg-digital-native.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-digital-native.jpg -------------------------------------------------------------------------------- /img/post-bg-dreamer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-dreamer.jpg -------------------------------------------------------------------------------- /img/post-bg-e2e-ux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-e2e-ux.jpg -------------------------------------------------------------------------------- /img/post-bg-farewell-flash.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-farewell-flash.jpg -------------------------------------------------------------------------------- /img/post-bg-halting.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-halting.jpg -------------------------------------------------------------------------------- /img/post-bg-infinity.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-infinity.jpg -------------------------------------------------------------------------------- /img/post-bg-ios9-web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-ios9-web.jpg -------------------------------------------------------------------------------- /img/post-bg-js-module.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-js-module.jpg -------------------------------------------------------------------------------- /img/post-bg-js-version.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-js-version.jpg -------------------------------------------------------------------------------- /img/post-bg-kuaidi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-kuaidi.jpg -------------------------------------------------------------------------------- /img/post-bg-miui-ux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-miui-ux.jpg -------------------------------------------------------------------------------- /img/post-bg-miui6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-miui6.jpg -------------------------------------------------------------------------------- /img/post-bg-nextgen-web-pwa.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-nextgen-web-pwa.jpg -------------------------------------------------------------------------------- /img/post-bg-os-metro.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-os-metro.jpg -------------------------------------------------------------------------------- /img/post-bg-re-vs-ng2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-re-vs-ng2.jpg -------------------------------------------------------------------------------- /img/post-bg-rwd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-rwd.jpg -------------------------------------------------------------------------------- /img/post-bg-see-u-ali.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-see-u-ali.jpg -------------------------------------------------------------------------------- /img/post-bg-universe.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-universe.jpg -------------------------------------------------------------------------------- /img/post-bg-unix-linux.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-unix-linux.jpg -------------------------------------------------------------------------------- /img/post-bg-web.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-bg-web.jpg -------------------------------------------------------------------------------- /img/post-sample-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/img/post-sample-image.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | description: "「离开世界之前 一切都是过程」" 4 | --- 5 | 6 | {% for post in paginator.posts %} 7 | <div class="post-preview"> 8 | <a href="{{ post.url | prepend: site.baseurl }}"> 9 | <h2 class="post-title"> 10 | {{ post.title }} 11 | </h2> 12 | {% if post.subtitle %} 13 | <h3 class="post-subtitle"> 14 | {{ post.subtitle }} 15 | </h3> 16 | {% endif %} 17 | <div class="post-content-preview"> 18 | {% if post.lang == 'en' %} 19 | {{ post.content | strip_html | truncate:300 }} 20 | {% else %} 21 | {{ post.content | strip_html | truncate:200 }} 22 | {% endif %} 23 | </div> 24 | </a> 25 | <p class="post-meta"> 26 | Posted by {% if post.author %}{{ post.author }}{% else %}{{ site.title }}{% endif %} on {{ post.date | date: "%B %-d, %Y" }} 27 | </p> 28 | </div> 29 | <hr> 30 | {% endfor %} 31 | 32 | <!-- Pager --> 33 | {% if paginator.total_pages > 1 %} 34 | <ul class="pager"> 35 | {% if paginator.previous_page %} 36 | <li class="previous"> 37 | <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">← Newer Posts</a> 38 | </li> 39 | {% endif %} 40 | {% if paginator.next_page %} 41 | <li class="next"> 42 | <a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Older Posts →</a> 43 | </li> 44 | {% endif %} 45 | </ul> 46 | {% endif %} 47 | -------------------------------------------------------------------------------- /js/animatescroll.min.js: -------------------------------------------------------------------------------- 1 | /* Coded by Ramswaroop */ 2 | (function(e){e.easing["jswing"]=e.easing["swing"];e.extend(e.easing,{def:"easeOutQuad",swing:function(t,n,r,i,s){return e.easing[e.easing.def](t,n,r,i,s)},easeInQuad:function(e,t,n,r,i){return r*(t/=i)*t+n},easeOutQuad:function(e,t,n,r,i){return-r*(t/=i)*(t-2)+n},easeInOutQuad:function(e,t,n,r,i){if((t/=i/2)<1)return r/2*t*t+n;return-r/2*(--t*(t-2)-1)+n},easeInCubic:function(e,t,n,r,i){return r*(t/=i)*t*t+n},easeOutCubic:function(e,t,n,r,i){return r*((t=t/i-1)*t*t+1)+n},easeInOutCubic:function(e,t,n,r,i){if((t/=i/2)<1)return r/2*t*t*t+n;return r/2*((t-=2)*t*t+2)+n},easeInQuart:function(e,t,n,r,i){return r*(t/=i)*t*t*t+n},easeOutQuart:function(e,t,n,r,i){return-r*((t=t/i-1)*t*t*t-1)+n},easeInOutQuart:function(e,t,n,r,i){if((t/=i/2)<1)return r/2*t*t*t*t+n;return-r/2*((t-=2)*t*t*t-2)+n},easeInQuint:function(e,t,n,r,i){return r*(t/=i)*t*t*t*t+n},easeOutQuint:function(e,t,n,r,i){return r*((t=t/i-1)*t*t*t*t+1)+n},easeInOutQuint:function(e,t,n,r,i){if((t/=i/2)<1)return r/2*t*t*t*t*t+n;return r/2*((t-=2)*t*t*t*t+2)+n},easeInSine:function(e,t,n,r,i){return-r*Math.cos(t/i*(Math.PI/2))+r+n},easeOutSine:function(e,t,n,r,i){return r*Math.sin(t/i*(Math.PI/2))+n},easeInOutSine:function(e,t,n,r,i){return-r/2*(Math.cos(Math.PI*t/i)-1)+n},easeInExpo:function(e,t,n,r,i){return t==0?n:r*Math.pow(2,10*(t/i-1))+n},easeOutExpo:function(e,t,n,r,i){return t==i?n+r:r*(-Math.pow(2,-10*t/i)+1)+n},easeInOutExpo:function(e,t,n,r,i){if(t==0)return n;if(t==i)return n+r;if((t/=i/2)<1)return r/2*Math.pow(2,10*(t-1))+n;return r/2*(-Math.pow(2,-10*--t)+2)+n},easeInCirc:function(e,t,n,r,i){return-r*(Math.sqrt(1-(t/=i)*t)-1)+n},easeOutCirc:function(e,t,n,r,i){return r*Math.sqrt(1-(t=t/i-1)*t)+n},easeInOutCirc:function(e,t,n,r,i){if((t/=i/2)<1)return-r/2*(Math.sqrt(1-t*t)-1)+n;return r/2*(Math.sqrt(1-(t-=2)*t)+1)+n},easeInElastic:function(e,t,n,r,i){var s=1.70158;var o=0;var u=r;if(t==0)return n;if((t/=i)==1)return n+r;if(!o)o=i*.3;if(u<Math.abs(r)){u=r;var s=o/4}else var s=o/(2*Math.PI)*Math.asin(r/u);return-(u*Math.pow(2,10*(t-=1))*Math.sin((t*i-s)*2*Math.PI/o))+n},easeOutElastic:function(e,t,n,r,i){var s=1.70158;var o=0;var u=r;if(t==0)return n;if((t/=i)==1)return n+r;if(!o)o=i*.3;if(u<Math.abs(r)){u=r;var s=o/4}else var s=o/(2*Math.PI)*Math.asin(r/u);return u*Math.pow(2,-10*t)*Math.sin((t*i-s)*2*Math.PI/o)+r+n},easeInOutElastic:function(e,t,n,r,i){var s=1.70158;var o=0;var u=r;if(t==0)return n;if((t/=i/2)==2)return n+r;if(!o)o=i*.3*1.5;if(u<Math.abs(r)){u=r;var s=o/4}else var s=o/(2*Math.PI)*Math.asin(r/u);if(t<1)return-.5*u*Math.pow(2,10*(t-=1))*Math.sin((t*i-s)*2*Math.PI/o)+n;return u*Math.pow(2,-10*(t-=1))*Math.sin((t*i-s)*2*Math.PI/o)*.5+r+n},easeInBack:function(e,t,n,r,i,s){if(s==undefined)s=1.70158;return r*(t/=i)*t*((s+1)*t-s)+n},easeOutBack:function(e,t,n,r,i,s){if(s==undefined)s=1.70158;return r*((t=t/i-1)*t*((s+1)*t+s)+1)+n},easeInOutBack:function(e,t,n,r,i,s){if(s==undefined)s=1.70158;if((t/=i/2)<1)return r/2*t*t*(((s*=1.525)+1)*t-s)+n;return r/2*((t-=2)*t*(((s*=1.525)+1)*t+s)+2)+n},easeInBounce:function(t,n,r,i,s){return i-e.easing.easeOutBounce(t,s-n,0,i,s)+r},easeOutBounce:function(e,t,n,r,i){if((t/=i)<1/2.75){return r*7.5625*t*t+n}else if(t<2/2.75){return r*(7.5625*(t-=1.5/2.75)*t+.75)+n}else if(t<2.5/2.75){return r*(7.5625*(t-=2.25/2.75)*t+.9375)+n}else{return r*(7.5625*(t-=2.625/2.75)*t+.984375)+n}},easeInOutBounce:function(t,n,r,i,s){if(n<s/2)return e.easing.easeInBounce(t,n*2,0,i,s)*.5+r;return e.easing.easeOutBounce(t,n*2-s,0,i,s)*.5+i*.5+r}});e.fn.animatescroll=function(t){var n=e.extend({},e.fn.animatescroll.defaults,t);if(typeof n.onScrollStart=="function"){n.onScrollStart.call(this)}if(n.element=="html,body"){var r=this.offset().top;e(n.element).stop().animate({scrollTop:r-n.padding},n.scrollSpeed,n.easing)}else{e(n.element).stop().animate({scrollTop:this.offset().top-this.parent().offset().top+this.parent().scrollTop()-n.padding},n.scrollSpeed,n.easing)}setTimeout(function(){if(typeof n.onScrollEnd=="function"){n.onScrollEnd.call(this)}},n.scrollSpeed)};e.fn.animatescroll.defaults={easing:"swing",scrollSpeed:800,padding:0,element:"html,body"}})(jQuery) -------------------------------------------------------------------------------- /js/hux-blog.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Clean Blog v1.0.0 (http://startbootstrap.com) 3 | * Copyright 2015 Start Bootstrap 4 | * Licensed under Apache 2.0 (https://github.com/IronSummitMedia/startbootstrap/blob/gh-pages/LICENSE) 5 | */ 6 | 7 | /*! 8 | * Hux Blog v1.6.0 (http://startbootstrap.com) 9 | * Copyright 2016 @huxpro 10 | * Licensed under Apache 2.0 11 | */ 12 | 13 | // Tooltip Init 14 | // Unuse by Hux since V1.6: Titles now display by default so there is no need for tooltip 15 | // $(function() { 16 | // $("[data-toggle='tooltip']").tooltip(); 17 | // }); 18 | 19 | 20 | // make all images responsive 21 | /* 22 | * Unuse by Hux 23 | * actually only Portfolio-Pages can't use it and only post-img need it. 24 | * so I modify the _layout/post and CSS to make post-img responsive! 25 | */ 26 | // $(function() { 27 | // $("img").addClass("img-responsive"); 28 | // }); 29 | 30 | // responsive tables 31 | $(document).ready(function() { 32 | $("table").wrap("<div class='table-responsive'></div>"); 33 | $("table").addClass("table"); 34 | }); 35 | 36 | // responsive embed videos 37 | $(document).ready(function() { 38 | $('iframe[src*="youtube.com"]').wrap('<div class="embed-responsive embed-responsive-16by9"></div>'); 39 | $('iframe[src*="youtube.com"]').addClass('embed-responsive-item'); 40 | $('iframe[src*="vimeo.com"]').wrap('<div class="embed-responsive embed-responsive-16by9"></div>'); 41 | $('iframe[src*="vimeo.com"]').addClass('embed-responsive-item'); 42 | }); 43 | 44 | // Navigation Scripts to Show Header on Scroll-Up 45 | jQuery(document).ready(function($) { 46 | var MQL = 1170; 47 | 48 | //primary navigation slide-in effect 49 | if ($(window).width() > MQL) { 50 | var headerHeight = $('.navbar-custom').height(), 51 | bannerHeight = $('.intro-header .container').height(); 52 | $(window).on('scroll', { 53 | previousTop: 0 54 | }, 55 | function() { 56 | var currentTop = $(window).scrollTop(), 57 | $catalog = $('.side-catalog'); 58 | 59 | //check if user is scrolling up by mouse or keyborad 60 | if (currentTop < this.previousTop) { 61 | //if scrolling up... 62 | if (currentTop > 0 && $('.navbar-custom').hasClass('is-fixed')) { 63 | $('.navbar-custom').addClass('is-visible'); 64 | } else { 65 | $('.navbar-custom').removeClass('is-visible is-fixed'); 66 | } 67 | } else { 68 | //if scrolling down... 69 | $('.navbar-custom').removeClass('is-visible'); 70 | if (currentTop > headerHeight && !$('.navbar-custom').hasClass('is-fixed')) $('.navbar-custom').addClass('is-fixed'); 71 | } 72 | this.previousTop = currentTop; 73 | 74 | 75 | //adjust the appearance of side-catalog 76 | $catalog.show() 77 | if (currentTop > (bannerHeight + 41)) { 78 | $catalog.addClass('fixed') 79 | } else { 80 | $catalog.removeClass('fixed') 81 | } 82 | }); 83 | } 84 | }); -------------------------------------------------------------------------------- /js/hux-blog.min.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){$("table").wrap("<div class='table-responsive'></div>"),$("table").addClass("table")}),$(document).ready(function(){$('iframe[src*="youtube.com"]').wrap('<div class="embed-responsive embed-responsive-16by9"></div>'),$('iframe[src*="youtube.com"]').addClass("embed-responsive-item"),$('iframe[src*="vimeo.com"]').wrap('<div class="embed-responsive embed-responsive-16by9"></div>'),$('iframe[src*="vimeo.com"]').addClass("embed-responsive-item")}),jQuery(document).ready(function(i){var a,o;1170<i(window).width()&&(a=i(".navbar-custom").height(),o=i(".intro-header .container").height(),i(window).on("scroll",{previousTop:0},function(){var s=i(window).scrollTop(),e=i(".side-catalog");s<this.previousTop?0<s&&i(".navbar-custom").hasClass("is-fixed")?i(".navbar-custom").addClass("is-visible"):i(".navbar-custom").removeClass("is-visible is-fixed"):(i(".navbar-custom").removeClass("is-visible"),a<s&&!i(".navbar-custom").hasClass("is-fixed")&&i(".navbar-custom").addClass("is-fixed")),this.previousTop=s,e.show(),o+41<s?e.addClass("fixed"):e.removeClass("fixed")}))}); -------------------------------------------------------------------------------- /js/jquery.tagcloud.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | 3 | $.fn.tagcloud = function(options) { 4 | var opts = $.extend({}, $.fn.tagcloud.defaults, options); 5 | tagWeights = this.map(function(){ 6 | return $(this).attr("rel"); 7 | }); 8 | tagWeights = jQuery.makeArray(tagWeights).sort(compareWeights); 9 | lowest = tagWeights[0]; 10 | highest = tagWeights.pop(); 11 | range = highest - lowest; 12 | if(range === 0) {range = 1;} 13 | // Sizes 14 | if (opts.size) { 15 | fontIncr = (opts.size.end - opts.size.start)/range; 16 | } 17 | // Colors 18 | if (opts.color) { 19 | colorIncr = colorIncrement (opts.color, range); 20 | } 21 | return this.each(function() { 22 | weighting = $(this).attr("rel") - lowest; 23 | if (opts.size) { 24 | $(this).css({"font-size": opts.size.start + (weighting * fontIncr) + opts.size.unit}); 25 | } 26 | if (opts.color) { 27 | // change color to background-color 28 | $(this).css({"backgroundColor": tagColor(opts.color, colorIncr, weighting)}); 29 | } 30 | }); 31 | }; 32 | 33 | $.fn.tagcloud.defaults = { 34 | size: {start: 14, end: 18, unit: "pt"} 35 | }; 36 | 37 | // Converts hex to an RGB array 38 | function toRGB (code) { 39 | if (code.length == 4) { 40 | code = jQuery.map(/\w+/.exec(code), function(el) {return el + el; }).join(""); 41 | } 42 | hex = /(\w{2})(\w{2})(\w{2})/.exec(code); 43 | return [parseInt(hex[1], 16), parseInt(hex[2], 16), parseInt(hex[3], 16)]; 44 | } 45 | 46 | // Converts an RGB array to hex 47 | function toHex (ary) { 48 | return "#" + jQuery.map(ary, function(i) { 49 | hex = i.toString(16); 50 | hex = (hex.length == 1) ? "0" + hex : hex; 51 | return hex; 52 | }).join(""); 53 | } 54 | 55 | function colorIncrement (color, range) { 56 | return jQuery.map(toRGB(color.end), function(n, i) { 57 | return (n - toRGB(color.start)[i])/range; 58 | }); 59 | } 60 | 61 | function tagColor (color, increment, weighting) { 62 | rgb = jQuery.map(toRGB(color.start), function(n, i) { 63 | ref = Math.round(n + (increment[i] * weighting)); 64 | if (ref > 255) { 65 | ref = 255; 66 | } else { 67 | if (ref < 0) { 68 | ref = 0; 69 | } 70 | } 71 | return ref; 72 | }); 73 | return toHex(rgb); 74 | } 75 | 76 | function compareWeights(a, b) 77 | { 78 | return a - b; 79 | } 80 | 81 | })(jQuery); 82 | -------------------------------------------------------------------------------- /js/snackbar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SnackBar.js 3 | * 4 | * This small component is borrowed from 5 | * https://codepen.io/wibblymat/pen/avAjq 6 | */ 7 | 8 | 9 | var createSnackbar = (function() { 10 | // Any snackbar that is already shown 11 | var previous = null; 12 | 13 | /* 14 | <div class="paper-snackbar"> 15 | <button class="action">Dismiss</button> 16 | This is a longer message that won't fit on one line. It is, inevitably, quite a boring thing. Hopefully it is still useful. 17 | </div> 18 | */ 19 | 20 | return function(config) { 21 | var message = config.message, 22 | actionText = config.actionText, 23 | action = config.action, 24 | duration = config.duration; 25 | 26 | if (previous) { 27 | previous.dismiss(); 28 | } 29 | var snackbar = document.createElement('div'); 30 | snackbar.className = 'paper-snackbar'; 31 | snackbar.dismiss = function() { 32 | this.style.opacity = 0; 33 | }; 34 | var text = document.createTextNode(message); 35 | snackbar.appendChild(text); 36 | if (actionText) { 37 | if (!action) { 38 | action = snackbar.dismiss.bind(snackbar); 39 | } 40 | var actionButton = document.createElement('button'); 41 | actionButton.className = 'action'; 42 | actionButton.innerHTML = actionText; 43 | actionButton.addEventListener('click', action); 44 | snackbar.appendChild(actionButton); 45 | } 46 | setTimeout(function() { 47 | if (previous === this) { 48 | previous.dismiss(); 49 | } 50 | }.bind(snackbar), duration || 5000); 51 | 52 | snackbar.addEventListener('transitionend', function(event, elapsed) { 53 | if (event.propertyName === 'opacity' && this.style.opacity == 0) { 54 | this.parentElement.removeChild(this); 55 | if (previous === this) { 56 | previous = null; 57 | } 58 | } 59 | }.bind(snackbar)); 60 | 61 | 62 | 63 | previous = snackbar; 64 | document.body.appendChild(snackbar); 65 | // In order for the animations to trigger, I have to force the original style to be computed, and then change it. 66 | getComputedStyle(snackbar).bottom; 67 | snackbar.style.bottom = '0px'; 68 | snackbar.style.opacity = 1; 69 | }; 70 | })(); 71 | -------------------------------------------------------------------------------- /js/sw-registration.js: -------------------------------------------------------------------------------- 1 | /* =========================================================== 2 | * sw-registration.js 3 | * =========================================================== 4 | * Copyright 2016 @huxpro 5 | * Licensed under Apache 2.0 6 | * Register service worker. 7 | * ========================================================== */ 8 | 9 | // SW Version Upgrade Ref: <https://youtu.be/Gb9uI67tqV0> 10 | 11 | function handleRegistration(registration){ 12 | console.log('Service Worker Registered. ', registration) 13 | /** 14 | * ServiceWorkerRegistration.onupdatefound 15 | * The service worker registration's installing worker changes. 16 | */ 17 | registration.onupdatefound = (e) => { 18 | const installingWorker = registration.installing; 19 | installingWorker.onstatechange = (e) => { 20 | if (installingWorker.state !== 'installed') return; 21 | if (navigator.serviceWorker.controller) { 22 | console.log('SW is updated'); 23 | } else { 24 | console.log('A Visit without previous SW'); 25 | createSnackbar({ 26 | message: 'App ready for offline use.', 27 | duration: 3000 28 | }) 29 | } 30 | }; 31 | } 32 | } 33 | 34 | if(navigator.serviceWorker){ 35 | // For security reasons, a service worker can only control the pages 36 | // that are in the same directory level or below it. That's why we put sw.js at ROOT level. 37 | navigator.serviceWorker 38 | .register('/sw.js') 39 | .then((registration) => handleRegistration(registration)) 40 | .catch((error) => {console.log('ServiceWorker registration failed: ', error)}) 41 | 42 | // register message receiver 43 | // https://dbwriteups.wordpress.com/2015/11/16/service-workers-part-3-communication-between-sw-and-pages/ 44 | navigator.serviceWorker.onmessage = (e) => { 45 | console.log('SW: SW Broadcasting:', event); 46 | const data = e.data 47 | 48 | if(data.command == "UPDATE_FOUND"){ 49 | console.log("UPDATE_FOUND_BY_SW", data); 50 | createSnackbar({ 51 | message: "Content updated.", 52 | actionText:"refresh", 53 | action: function(e){location.reload()} 54 | }) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | 3 | .transition-all() { 4 | -webkit-transition: all 0.5s; 5 | -moz-transition: all 0.5s; 6 | transition: all 0.5s; 7 | } 8 | 9 | .background-cover() { 10 | -webkit-background-size: cover; 11 | -moz-background-size: cover; 12 | background-size: cover; 13 | -o-background-size: cover; 14 | } 15 | 16 | .monospace () { 17 | font-family: "Fira Code", Menlo, Monaco, Consolas, "Courier New", monospace; 18 | } 19 | 20 | .serif() { 21 | font-family: 'Lora', 'Times New Roman', serif; 22 | } 23 | 24 | .sans-serif () { 25 | /* Hux learn from 26 | * TypeIsBeautiful, 27 | * [This Post](http://zhuanlan.zhihu.com/ibuick/20186806) etc. 28 | */ 29 | font-family: 30 | // System Font // https://www.webkit.org/blog/3709/using-the-system-font-in-web-content/ 31 | -apple-system, // OSX ^10.11 & iOS ^9 San Francisco & 苹方 for Safari 32 | BlinkMacSystemFont, // OSX ^10.11 & iOS ^9 San Francisco & 苹方 for Blink 33 | 34 | // English First 35 | "Helvetica Neue", // OSX 36 | "Arial", // Win "Helvetica" 37 | //" Segoe UI", // Win ^8 38 | 39 | // Chinese Fallback 40 | "PingFang SC", // OSX ^10.11 & iOS ^9 苹方(华康信凭黑) 41 | "Hiragino Sans GB", // OSX ^10.6 冬青黑体 42 | "STHeiti", // OSX <10.6 & iOS <9 华文黑体 43 | "Microsoft YaHei", // Win 微软雅黑 44 | "Microsoft JhengHei", // Win 微软正黑 45 | "Source Han Sans SC", // SourceHan - begin 思源黑体 46 | "Noto Sans CJK SC", 47 | "Source Han Sans CN", 48 | "Noto Sans SC", 49 | "Source Han Sans TC", 50 | "Noto Sans CJK TC", // SourceHan - end 51 | "WenQuanYi Micro Hei", // Linux 文泉驿微米黑 52 | SimSun, // Win old 中易宋体 53 | sans-serif; // System Fallback 54 | 55 | line-height: 1.7; 56 | } 57 | -------------------------------------------------------------------------------- /less/search.less: -------------------------------------------------------------------------------- 1 | .search-page { 2 | position: fixed; 3 | top: 0; 4 | right: 0; 5 | bottom: 0; 6 | left: 0; 7 | z-index: 100; 8 | background: #fff; 9 | -webkit-transition: all 400ms cubic-bezier(0.32, 1, 0.23, 1); 10 | transition: all 400ms cubic-bezier(0.32, 1, 0.23, 1); 11 | -webkit-transform: translate(0, 100%); 12 | -ms-transform: translate(0, 100%); 13 | transform: translate(0, 100%); 14 | opacity: 0; 15 | 16 | &.search-active { 17 | opacity: 1; 18 | -webkit-transform: translate(0, 0) scale(1, 1); 19 | -ms-transform: translate(0, 0) scale(1, 1); 20 | transform: translate(0, 0) scale(1, 1); 21 | .search-main { 22 | opacity: 1; 23 | } 24 | } 25 | 26 | .search-main { 27 | padding-top: 80px; 28 | height: 100%; 29 | opacity: 0; 30 | -webkit-transition: all 400ms cubic-bezier(0.32, 1, 0.23, 1) 250ms; 31 | transition: all 400ms cubic-bezier(0.32, 1, 0.23, 1) 250ms; 32 | .row, 33 | .row > div { 34 | height: 100%; 35 | } 36 | } 37 | 38 | .search-icon-close-container { 39 | position: absolute; 40 | z-index: 1; 41 | padding: 16px; 42 | top: 0; 43 | right: 2px; 44 | i { 45 | font-size: 20px; 46 | } 47 | } 48 | 49 | #search-input { 50 | .monospace; 51 | 52 | // poorman's reset 53 | border: none; 54 | outline: none; 55 | padding: 0; 56 | margin: 0; 57 | // poorman's reset end 58 | 59 | width: 100%; 60 | font-size: 30px; 61 | font-weight: bold; 62 | color: @gray-dark; 63 | 64 | @media only screen and (min-width: 768px) { 65 | margin-left: 20px; 66 | } 67 | } 68 | 69 | #search-results { 70 | overflow: auto; 71 | height: 100%; 72 | -webkit-overflow-scrolling: touch; 73 | padding-bottom: 80px; 74 | } 75 | } 76 | 77 | .search-icon a, 78 | .search-icon-close { 79 | cursor: pointer; 80 | font-size: 30px; 81 | color: #311e3e; 82 | -webkit-transition: all 0.25s; 83 | transition: all 0.25s; 84 | } 85 | 86 | .search-icon a:hover, 87 | .search-icon-close:hover { 88 | opacity: 0.8; 89 | } 90 | 91 | .search-icon, 92 | .search-icon-close { 93 | font-size: 16px; 94 | } 95 | -------------------------------------------------------------------------------- /less/side-catalog.less: -------------------------------------------------------------------------------- 1 | // Directory Section 2 | 3 | .catalog-container { 4 | padding: 0px; 5 | } 6 | 7 | .side-catalog { 8 | &.fixed { 9 | position: fixed; 10 | top: -21px; 11 | } 12 | &.fold { 13 | .catalog-toggle::before { 14 | content: "+"; 15 | } 16 | .catalog-body { 17 | display: none; 18 | } 19 | } 20 | .catalog-toggle::before { 21 | content: "−"; 22 | position: relative; 23 | margin-right: 5px; 24 | bottom: 1px; 25 | } 26 | display: block; 27 | overflow: auto; 28 | height: 100%; 29 | padding-bottom: 40px; 30 | width: 195px; 31 | .catalog-body { 32 | position: relative; 33 | list-style: none; 34 | height: auto; 35 | overflow: hidden; 36 | padding-left: 0px; 37 | padding-right: 5px; 38 | text-indent: 0; 39 | li { 40 | position: relative; 41 | list-style: none; 42 | a { 43 | padding-left: 10px; 44 | max-width: 180px; 45 | display: inline-block; 46 | vertical-align: middle; 47 | height: 30px; 48 | line-height: 30px; 49 | overflow: hidden; 50 | text-decoration: none; 51 | white-space: nowrap; 52 | text-overflow: ellipsis; 53 | } 54 | } 55 | .h1_nav, 56 | .h2_nav { 57 | margin-left: 0; 58 | font-size: 13px; 59 | font-weight: bold; 60 | } 61 | .h3_nav { 62 | margin-left: 6px; 63 | font-size: 13px; 64 | font-weight: bold; 65 | } 66 | .h4_nav { 67 | margin-left: 12px; 68 | font-size: 12px; 69 | a { 70 | max-width: 170px; 71 | } 72 | } 73 | .h5_nav .h6_nav { 74 | margin-left: 18px; 75 | font-size: 12px; 76 | a { 77 | max-width: 170px; 78 | } 79 | } 80 | .active { 81 | a { 82 | color: #0085a1 !important; 83 | } 84 | border-radius: 4px; 85 | background-color: #f5f5f5; 86 | } 87 | } 88 | } 89 | 90 | @media (max-width: 1200px) { 91 | .side-catalog { 92 | display: none; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /less/sidebar.less: -------------------------------------------------------------------------------- 1 | @import "variables.less"; 2 | 3 | // Sidebar Components 4 | 5 | // Large Screen 6 | @media (min-width: 1200px) { 7 | .post-container, 8 | .sidebar-container { 9 | padding-right: 5%; 10 | } 11 | } 12 | @media (min-width: 768px) { 13 | .post-container { 14 | padding-right: 5%; 15 | } 16 | } 17 | 18 | // Container of Sidebar, also Friends 19 | .sidebar-container { 20 | color: @gray-light; 21 | font-size: 14px; 22 | h5 { 23 | color: @brand-gray; 24 | padding-bottom: 1em; 25 | a { 26 | color: @brand-gray !important; 27 | text-decoration: none; 28 | } 29 | } 30 | a { 31 | color: @gray-light !important; 32 | &:hover, 33 | &:active { 34 | color: @brand-primary !important; 35 | } 36 | } 37 | .tags { 38 | a { 39 | border-color: @gray-light; 40 | &:hover, 41 | &:active { 42 | border-color: @brand-primary; 43 | } 44 | } 45 | } 46 | .short-about { 47 | img { 48 | width: 80%; 49 | display: block; 50 | border-radius: 5px; 51 | margin-bottom: 20px; 52 | } 53 | p { 54 | margin-top: 0px; 55 | margin-bottom: 20px; 56 | } 57 | .list-inline > li { 58 | padding-left: 0px; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /less/variables.less: -------------------------------------------------------------------------------- 1 | // Variables 2 | 3 | @brand-primary: #0085a1; 4 | @brand-gray: #a3a3a3; 5 | 6 | @gray-dark: lighten(black, 25%); 7 | @gray-light: lighten(black, 75%); 8 | 9 | @white-faded: fade(white, 80%); 10 | -------------------------------------------------------------------------------- /offline.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Offline 4 | hide-in-nav: true 5 | description: "阅读过的页面可以在离线时访问哦 ;)" 6 | header-img: "img/404-bg.jpg" 7 | permalink: /offline.html 8 | --- 9 | 10 | 11 | <!-- Page Header --> 12 | {% include intro-header.html type="page" %} 13 | 14 | <script> 15 | document.body.classList.add('page-fullscreen'); 16 | </script> 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hux-blog", 3 | "title": "Hux Blog", 4 | "author": "Hux <huxpro@gmail.com>", 5 | "version": "1.8.2", 6 | "homepage": "http://huxpro.github.io", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/Huxpro/huxpro.github.io" 10 | }, 11 | "bugs": "https://github.com/Huxpro/huxpro.github.io/issues", 12 | "devDependencies": { 13 | "grunt": ">=1.3.0", 14 | "grunt-banner": "~0.2.3", 15 | "grunt-contrib-less": "^2.0.0", 16 | "grunt-contrib-uglify": "^4.0.1", 17 | "grunt-contrib-watch": "^1.1.0" 18 | }, 19 | "scripts": { 20 | "start": "bundle exec jekyll serve", 21 | "dev": "grunt watch & npm run start", 22 | "boil": "git push boilerplate boilerplate:master", 23 | "push": "git push origin master --tag" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pwa/icons/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/pwa/icons/128.png -------------------------------------------------------------------------------- /pwa/icons/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Huxpro/huxpro.github.io/a2ab0900be50d5f8695a18e22c5d61ebcc82afa7/pwa/icons/512.png -------------------------------------------------------------------------------- /pwa/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Hux Blog", 3 | "short_name": "Hux Blog", 4 | "description": "About an engineer & designer who loves web.", 5 | "icons": [{ 6 | "src": "icons/128.png", 7 | "sizes": "128x128", 8 | "type": "image/png" 9 | }, { 10 | "src": "icons/512.png", 11 | "sizes": "512x512", 12 | "type": "image/png" 13 | }], 14 | "background_color": "#fff", 15 | "theme_color": "#000", 16 | "start_url": "/", 17 | "display": "standalone", 18 | "orientation": "portrait" 19 | } 20 | -------------------------------------------------------------------------------- /search.json: -------------------------------------------------------------------------------- 1 | --- 2 | layout: null 3 | --- 4 | [ 5 | {% for post in site.posts %} 6 | { 7 | "title" : "{{ post.title | escape }}", 8 | "subtitle" : "{{ post.subtitle | escape }}", 9 | "tags" : "{{ post.tags | join: ', ' }}", 10 | "url" : "{{ site.baseurl }}{{ post.url }}", 11 | "date" : "{{ post.date }}" 12 | } {% unless forloop.last %},{% endunless %} 13 | {% endfor %} 14 | ] --------------------------------------------------------------------------------