Utensil's index site for utensil.github.io utensil.github.io/
0

Configure Feed

Select the types of activity you want to include in your feed.

Upgrade Ruby and Middleman stack

+491 -128
+6 -10
.github/workflows/ruby.yml
··· 21 21 runs-on: ubuntu-latest 22 22 strategy: 23 23 matrix: 24 - ruby-version: ['2.7'] 24 + ruby-version: ['3.4.8'] 25 25 environment: 26 26 name: github-pages 27 27 url: ${{ steps.deployment.outputs.page_url }} 28 28 steps: 29 29 - name: Checkout 🛎️ 30 - uses: actions/checkout@v3 30 + uses: actions/checkout@v6 31 31 - name: Set up Ruby 32 - # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby, 33 - # change this to (see https://github.com/ruby/setup-ruby#versioning): 34 - # uses: ruby/setup-ruby@v1 35 - uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e 32 + uses: ruby/setup-ruby@v1 36 33 with: 37 34 ruby-version: ${{ matrix.ruby-version }} 38 35 bundler-cache: true # runs 'bundle install' and caches installed gems automatically 39 - bundler: 1.17.3 40 36 - name: Install and Build 🔧 41 37 run: | 42 38 bundle exec middleman build --verbose 43 39 - name: Setup Pages 44 - uses: actions/configure-pages@v3 40 + uses: actions/configure-pages@v5 45 41 - name: Upload artifact 46 - uses: actions/upload-pages-artifact@v2 42 + uses: actions/upload-pages-artifact@v4 47 43 with: 48 44 path: 'build' 49 45 - name: Deploy to GitHub Pages 🚀 50 46 id: deployment 51 - uses: actions/deploy-pages@v2 47 + uses: actions/deploy-pages@v4
+1 -1
.gitignore
··· 2 2 /build 3 3 Thumbs.db 4 4 .bundle/ 5 - Gemfile.lock 5 + vendor/bundle/ 6 6 .DS_Store
+1
.ruby-version
··· 1 + 3.4.8
+1
.tool-versions
··· 1 + ruby 3.4.8
+11 -9
Gemfile
··· 1 + ruby '3.4.8' 2 + 1 3 source 'https://rubygems.org/' 2 4 3 - gem 'sass' 4 - gem 'ya2yaml' 5 - gem 'haml', '~>5.2' 6 - gem 'middleman', '~> 3.4' 7 - gem 'middleman-blog', '~> 3.5' 5 + gem 'sass', '~> 3.7' 6 + gem 'ya2yaml', '~> 0.31' 7 + gem 'haml', '~> 6.3' 8 + gem 'middleman', '4.6.2' 9 + gem 'middleman-blog', '4.2.0' 8 10 gem 'middleman-minify-html', '~> 3.4' 9 - gem 'bourbon', '~> 5.1' 10 - gem 'neat', '~> 4.0' 11 - gem 'html-pipeline' 12 - gem 'commonmarker' 11 + gem 'html-pipeline', '~> 2.14' 12 + gem 'commonmarker', '~> 0.23' 13 13 gem 'ruby-enum', '~> 0.7.2' 14 + gem 'thor', '1.4.0' 15 + gem 'webrick', '~> 1.9' 14 16 # gem 'redcarpet', '~> 3.5' 15 17 # gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw] # http://stackoverflow.com/questions/23022258/tzinfodatasourcenotfound-error-starting-rails-v4-1-0-server-on-windows 16 18 # gem 'haml-coderay'
+194
Gemfile.lock
··· 1 + GEM 2 + remote: https://rubygems.org/ 3 + specs: 4 + activesupport (8.1.3) 5 + base64 6 + bigdecimal 7 + concurrent-ruby (~> 1.0, >= 1.3.1) 8 + connection_pool (>= 2.2.5) 9 + drb 10 + i18n (>= 1.6, < 2) 11 + json 12 + logger (>= 1.4.2) 13 + minitest (>= 5.1) 14 + securerandom (>= 0.3) 15 + tzinfo (~> 2.0, >= 2.0.5) 16 + uri (>= 0.13.1) 17 + addressable (2.9.0) 18 + public_suffix (>= 2.0.2, < 8.0) 19 + base64 (0.3.0) 20 + bigdecimal (4.1.2) 21 + coffee-script (2.4.1) 22 + coffee-script-source 23 + execjs 24 + coffee-script-source (1.12.2) 25 + commonmarker (0.23.12) 26 + concurrent-ruby (1.3.6) 27 + connection_pool (3.0.2) 28 + contracts (0.17.3) 29 + dotenv (3.2.0) 30 + drb (2.2.3) 31 + erubi (1.13.1) 32 + execjs (2.10.1) 33 + fast_blank (1.0.1) 34 + fastimage (2.4.1) 35 + ffi (1.17.4-aarch64-linux-gnu) 36 + ffi (1.17.4-aarch64-linux-musl) 37 + ffi (1.17.4-arm-linux-gnu) 38 + ffi (1.17.4-arm-linux-musl) 39 + ffi (1.17.4-arm64-darwin) 40 + ffi (1.17.4-x86_64-darwin) 41 + ffi (1.17.4-x86_64-linux-gnu) 42 + ffi (1.17.4-x86_64-linux-musl) 43 + haml (6.4.0) 44 + temple (>= 0.8.2) 45 + thor 46 + tilt 47 + hamster (3.0.0) 48 + concurrent-ruby (~> 1.0) 49 + hashie (5.1.0) 50 + logger 51 + html-pipeline (2.14.3) 52 + activesupport (>= 2) 53 + nokogiri (>= 1.4) 54 + htmlcompressor (0.2.0) 55 + i18n (1.14.8) 56 + concurrent-ruby (~> 1.0) 57 + json (2.19.5) 58 + kramdown (2.5.2) 59 + rexml (>= 3.4.4) 60 + listen (3.10.0) 61 + logger 62 + rb-fsevent (~> 0.10, >= 0.10.3) 63 + rb-inotify (~> 0.9, >= 0.9.10) 64 + logger (1.7.0) 65 + memoist (0.16.2) 66 + middleman (4.6.2) 67 + middleman-cli (= 4.6.2) 68 + middleman-core (= 4.6.2) 69 + middleman-blog (4.2.0) 70 + addressable (~> 2.3) 71 + middleman-core (>= 4.0.0) 72 + tzinfo (>= 0.3.0) 73 + middleman-cli (4.6.2) 74 + thor (>= 0.17.0, < 2) 75 + middleman-core (4.6.2) 76 + activesupport (>= 6.1) 77 + addressable (~> 2.4) 78 + bundler (~> 2.0) 79 + coffee-script (~> 2.2) 80 + contracts 81 + dotenv 82 + erubi 83 + execjs (~> 2.0) 84 + fast_blank 85 + fastimage (~> 2.0) 86 + haml (>= 4.0.5) 87 + hamster (~> 3.0) 88 + hashie (>= 3.4, < 6.0) 89 + i18n (>= 1.6, < 1.15) 90 + kramdown (~> 2.4) 91 + listen (~> 3.0) 92 + memoist (~> 0.14) 93 + padrino-helpers (~> 0.15.0) 94 + parallel 95 + rack (>= 3) 96 + rackup 97 + sassc (~> 2.0) 98 + servolux 99 + tilt (~> 2.2) 100 + toml 101 + uglifier (>= 3, < 5) 102 + webrick 103 + middleman-minify-html (3.4.1) 104 + htmlcompressor (~> 0.2.0) 105 + middleman-core (>= 3.2) 106 + minitest (6.0.6) 107 + drb (~> 2.0) 108 + prism (~> 1.5) 109 + nokogiri (1.19.3-aarch64-linux-gnu) 110 + racc (~> 1.4) 111 + nokogiri (1.19.3-aarch64-linux-musl) 112 + racc (~> 1.4) 113 + nokogiri (1.19.3-arm-linux-gnu) 114 + racc (~> 1.4) 115 + nokogiri (1.19.3-arm-linux-musl) 116 + racc (~> 1.4) 117 + nokogiri (1.19.3-arm64-darwin) 118 + racc (~> 1.4) 119 + nokogiri (1.19.3-x86_64-darwin) 120 + racc (~> 1.4) 121 + nokogiri (1.19.3-x86_64-linux-gnu) 122 + racc (~> 1.4) 123 + nokogiri (1.19.3-x86_64-linux-musl) 124 + racc (~> 1.4) 125 + padrino-helpers (0.15.3) 126 + i18n (>= 0.6.7, < 2) 127 + padrino-support (= 0.15.3) 128 + tilt (>= 1.4.1, < 3) 129 + padrino-support (0.15.3) 130 + parallel (2.1.0) 131 + parslet (2.0.0) 132 + prism (1.9.0) 133 + public_suffix (7.0.5) 134 + racc (1.8.1) 135 + rack (3.2.6) 136 + rackup (2.3.1) 137 + rack (>= 3) 138 + rb-fsevent (0.11.2) 139 + rb-inotify (0.11.1) 140 + ffi (~> 1.0) 141 + rexml (3.4.4) 142 + ruby-enum (0.7.2) 143 + i18n 144 + sass (3.7.4) 145 + sass-listen (~> 4.0.0) 146 + sass-listen (4.0.0) 147 + rb-fsevent (~> 0.9, >= 0.9.4) 148 + rb-inotify (~> 0.9, >= 0.9.7) 149 + sassc (2.4.0) 150 + ffi (~> 1.9) 151 + securerandom (0.4.1) 152 + servolux (0.13.0) 153 + temple (0.10.4) 154 + thor (1.4.0) 155 + tilt (2.7.0) 156 + toml (0.3.0) 157 + parslet (>= 1.8.0, < 3.0.0) 158 + tzinfo (2.0.6) 159 + concurrent-ruby (~> 1.0) 160 + uglifier (4.2.1) 161 + execjs (>= 0.3.0, < 3) 162 + uri (1.1.1) 163 + webrick (1.9.2) 164 + ya2yaml (0.31) 165 + 166 + PLATFORMS 167 + aarch64-linux-gnu 168 + aarch64-linux-musl 169 + arm-linux-gnu 170 + arm-linux-musl 171 + arm64-darwin 172 + x86_64-darwin 173 + x86_64-linux-gnu 174 + x86_64-linux-musl 175 + 176 + DEPENDENCIES 177 + commonmarker (~> 0.23) 178 + haml (~> 6.3) 179 + html-pipeline (~> 2.14) 180 + middleman (= 4.6.2) 181 + middleman-blog (= 4.2.0) 182 + middleman-minify-html (~> 3.4) 183 + ruby-enum (~> 0.7.2) 184 + sass (~> 3.7) 185 + thor (= 1.4.0) 186 + wdm (~> 0.1) 187 + webrick (~> 1.9) 188 + ya2yaml (~> 0.31) 189 + 190 + RUBY VERSION 191 + ruby 3.4.8p72 192 + 193 + BUNDLED WITH 194 + 2.6.9
+78 -3
config.rb
··· 102 102 end 103 103 return ret 104 104 end 105 + 106 + def section_articles(blog_name = current_page.data.blog) 107 + blog(blog_name).articles.sort_by(&:source_file).reverse 108 + end 109 + 110 + def section_tags(blog_name = current_page.data.blog) 111 + blog(blog_name).tags.sort_by { |_, articles| -articles.size } 112 + end 113 + 114 + def article_body(article) 115 + article.body.to_s.encode('UTF-8', invalid: :replace, undef: :replace, replace: '') 116 + end 105 117 end 106 118 107 119 # Markdown ··· 130 142 require 'lib/mytemplate' 131 143 set :markdown_engine, :MarkdownHtmlFilter 132 144 133 - set :md, :layout_engine => :haml 134 - set :haml, :layout_engine => :haml #, :encoding => 'utf-8' 135 - 136 145 # with_layout 'tech_layout.haml' do 137 146 # page "/tech/*.html" 138 147 # end ··· 148 157 set :layout, false 149 158 150 159 require "middleman-blog" 160 + require "middleman-blog/blog_data" 161 + 162 + module Middleman 163 + module Blog 164 + module BlogArticle 165 + def slug 166 + path_part('title') 167 + end 168 + 169 + def content_type 170 + 'text/html; charset=utf-8' 171 + end 172 + end 173 + 174 + class BlogData 175 + def permalink_options(resource, extra = {}) 176 + params = resource.metadata[:page].slice(*@permalink_template.variables.map(&:to_sym)) 177 + 178 + params.each do |key, value| 179 + params[key] = safe_parameterize(value, preserve_underscores: @options.preserve_underscores_in_slugs) 180 + end 181 + 182 + params 183 + .merge(date_to_params(resource.date)) 184 + .merge(lang: resource.lang.to_s, locale: resource.locale.to_s, title: raw_title_from_source(resource)) 185 + .merge(extra) 186 + end 187 + 188 + def raw_title_from_source(resource) 189 + basename = File.basename(resource.source_file.to_s) 190 + basename = basename.sub(/\.[^.]+\z/, '') 191 + basename.sub(/\A\d{4}-\d{2}-\d{2}-/, '') 192 + end 193 + end 194 + end 195 + end 196 + 197 + class PreserveBlogFileBasenamePaths 198 + def manipulate_resource_list(resources) 199 + resources.each do |resource| 200 + source_file = resource.source_file.to_s 201 + match = source_file.match(%r{/source/(tech|writings|blogs)/(\d{4})-(\d{2})-(\d{2})-(.+)\.(md|haml)\z}) 202 + next unless match 203 + 204 + article_name = match[5] 205 + extension = article_name.end_with?('.html') ? '' : '.html' 206 + resource.destination_path = "#{match[1]}/#{match[2]}/#{match[3]}/#{match[4]}/#{article_name}#{extension}" 207 + def resource.content_type 208 + 'text/html; charset=utf-8' 209 + end 210 + end 211 + 212 + resources 213 + end 214 + end 215 + 151 216 activate :blog do |tech_blog| 152 217 tech_blog.name = 'tech' 153 218 tech_blog.prefix = 'tech' 219 + tech_blog.sources = '{year}-{month}-{day}-{title}' 220 + tech_blog.permalink = '/{year}/{month}/{day}/{title}.html' 154 221 tech_blog.layout = 'blog_layout' 155 222 end 156 223 157 224 activate :blog do |writings_blog| 158 225 writings_blog.name = 'writings' 159 226 writings_blog.prefix = 'writings' 227 + writings_blog.sources = '{year}-{month}-{day}-{title}' 228 + writings_blog.permalink = '/{year}/{month}/{day}/{title}.html' 160 229 writings_blog.layout = 'blog_layout' 161 230 end 162 231 163 232 activate :blog do |blogs_blog| 164 233 blogs_blog.name = 'blogs' 165 234 blogs_blog.prefix = 'blogs' 235 + blogs_blog.sources = '{year}-{month}-{day}-{title}' 236 + blogs_blog.permalink = '/{year}/{month}/{day}/{title}.html' 166 237 blogs_blog.layout = 'blog_layout_en' 167 238 blogs_blog.paginate = true 168 239 blogs_blog.per_page = 5 240 + end 241 + 242 + after_configuration do 243 + sitemap.register_resource_list_manipulator(:preserve_blog_file_basename_paths, PreserveBlogFileBasenamePaths.new, 60) 169 244 end 170 245 171 246 #ignore '/writings/*.md'
+2 -2
source/blogs/calendar.haml source/blogs/calendar.html.haml
··· 4 4 --- 5 5 -# coding: utf-8 6 6 %section.calendar 7 - - blog.articles.group_by {|a| "#{a.date.year}" }.each do |year, year_articles| 7 + - section_articles.group_by {|a| "#{a.date.year}" }.each do |year, year_articles| 8 8 %h2= year 9 9 - year_articles.group_by {|a| "#{a.date.strftime("%B")}" }.each do |month, articles| 10 10 %div{:id => "calendar-#{month}" } ··· 13 13 - articles.sort_by { |a| a.source_file }.reverse.each do |article| 14 14 %li.listing-item 15 15 %time{:datetime => article.date}=article.date.strftime('%Y-%m-%d') 16 - %a{:href => article.url}=article.title 16 + %a{:href => article.url}=article.title
+1 -1
source/blogs/index.haml source/blogs/index.html.haml
··· 11 11 %a{:href => article.url} 12 12 =article.data['title'] 13 13 %div 14 - =article.app.render_template(article.source_file) 14 + != article_body(article)
+4 -4
source/blogs/tags.haml source/blogs/tags.html.haml
··· 5 5 -# coding: utf-8 6 6 %section.tags 7 7 #tag_cloud 8 - - blog.tags.each.sort_by{|tag, articles| -articles.size }.each do |tag_and_articles| 8 + - section_tags.each do |tag_and_articles| 9 9 - tag = tag_and_articles[0] 10 10 - articles = tag_and_articles[1] 11 11 %div{:id => "tag-#{tag}" } ··· 20 20 -# %backquote 21 21 -# = article.summary 22 22 - content_for :head do 23 - = stylesheet_link_tag "jqcloud.css" 23 + != stylesheet_link_tag "jqcloud.css" 24 24 - content_for :scripts do 25 - = javascript_include_tag "jqcloud-1.0.1.js" 26 - = javascript_include_tag "tags.js" 25 + != javascript_include_tag "jqcloud-1.0.1.js" 26 + != javascript_include_tag "tags.js"
+14 -14
source/layouts/blog_layout.haml
··· 6 6 / Always force latest IE rendering engine (even in intranet) &amp; Chrome Frame 7 7 %meta{:content => "IE=edge,chrome=1", "http-equiv" => "X-UA-Compatible"} 8 8 /[if (lt IE 9)&(!IEMobile)] 9 - = javascript_include_tag 'html5.js' 9 + != javascript_include_tag 'html5.js' 10 10 %meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"} 11 11 %title= current_page.data.title 12 - = stylesheet_link_tag 'site.css' 13 - = stylesheet_link_tag 'blog.css' 14 - = stylesheet_link_tag 'highlight/railscasts.css' 15 - = safe_yield_content :head 12 + != stylesheet_link_tag 'site.css' 13 + != stylesheet_link_tag 'blog.css' 14 + != stylesheet_link_tag 'highlight/railscasts.css' 15 + != safe_yield_content :head 16 16 /[if lt IE 9] 17 - = javascript_include_tag 'respond.js' 17 + != javascript_include_tag 'respond.js' 18 18 19 19 %body{:class => ''} 20 20 - @blog_name ||= blog.options.name || 'tech' ··· 32 32 %span 33 33 %a{:href => "/#{@blog_name}/about.html"} about 34 34 / = safe_yield_content :nav 35 - = safe_yield_content :sidebar 35 + != safe_yield_content :sidebar 36 36 %div.content 37 37 %header 38 38 - if is_blog_article? 39 39 %div.article_nav 40 40 %span.later 41 - - if next_ = current_article.next_article 41 + - if next_ = current_article.article_next 42 42 %a{:href => next_.url} 43 43 < 更新 44 44 - else 45 45 〇 已是最新 46 46 %span.earlier 47 - - if prev_ = current_article.previous_article 47 + - if prev_ = current_article.article_previous 48 48 %a{:href => prev_.url} 49 49 更早 > 50 50 - else ··· 53 53 %h1 54 54 = current_page.data['title'] 55 55 %article.markdown-body 56 - = yield 56 + != yield 57 57 - if is_blog_article? 58 58 %section.meta 59 59 %p ··· 93 93 } 94 94 / = safe_yield_content :footer 95 95 96 - = javascript_include_tag 'jquery-1.7.1.js' 96 + != javascript_include_tag 'jquery-1.7.1.js' 97 97 - code_mode = (current_page.data.code_mode || '').split(/\|/) 98 98 - if code_mode.include?('math') 99 - = javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML' 99 + != javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML' 100 100 - if code_mode.include?('xypic') 101 101 :javascript 102 102 window.mathUseXypic = true; ··· 153 153 } 154 154 }); 155 155 - if code_mode.include?('lang') || code_mode.size == 0 156 - = javascript_include_tag 'highlight.pack.js' 156 + != javascript_include_tag 'highlight.pack.js' 157 157 :javascript 158 158 hljs.initHighlightingOnLoad(); 159 159 // $(document).ready(function() { ··· 164 164 // (function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!== typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");for(g=0;g<i.length;g++)f(c,i[g]); b._i.push([a,e,d])};b.__SV=1.2}})(document,window.mixpanel||[]); mixpanel.init("eda89891866a7e90b6699df21e79ea61"); 165 165 // mixpanel.track("visit"); 166 166 /! end Mixpanel 167 - = safe_yield_content :scripts 167 + != safe_yield_content :scripts
+14 -14
source/layouts/blog_layout_en.haml
··· 6 6 / Always force latest IE rendering engine (even in intranet) &amp; Chrome Frame 7 7 %meta{:content => "IE=edge,chrome=1", "http-equiv" => "X-UA-Compatible"} 8 8 /[if (lt IE 9)&(!IEMobile)] 9 - = javascript_include_tag 'html5.js' 9 + != javascript_include_tag 'html5.js' 10 10 %meta{:content => "width=device-width, initial-scale=1.0", :name => "viewport"} 11 11 %title= current_page.data.title 12 - = stylesheet_link_tag 'site.css' 13 - = stylesheet_link_tag 'blog.css' 14 - = stylesheet_link_tag 'highlight/railscasts.css' 15 - = safe_yield_content :head 12 + != stylesheet_link_tag 'site.css' 13 + != stylesheet_link_tag 'blog.css' 14 + != stylesheet_link_tag 'highlight/railscasts.css' 15 + != safe_yield_content :head 16 16 /[if lt IE 9] 17 - = javascript_include_tag 'respond.js' 17 + != javascript_include_tag 'respond.js' 18 18 19 19 %body{:class => ''} 20 20 - @blog_name ||= blog.options.name || 'tech' ··· 32 32 %span 33 33 %a{:href => "/#{@blog_name}/about.html"} about 34 34 / = safe_yield_content :nav 35 - = safe_yield_content :sidebar 35 + != safe_yield_content :sidebar 36 36 %div.content 37 37 %header 38 38 - if is_blog_article? 39 39 %div.article_nav 40 40 %span.later 41 - - if next_ = current_article.next_article 41 + - if next_ = current_article.article_next 42 42 %a{:href => next_.url} 43 43 < Next 44 44 - else 45 45 〇 Latest 46 46 %span.earlier 47 - - if prev_ = current_article.previous_article 47 + - if prev_ = current_article.article_previous 48 48 %a{:href => prev_.url} 49 49 Prev > 50 50 - else ··· 53 53 %h1 54 54 = current_page.data['title'] 55 55 %article.markdown-body 56 - = yield 56 + != yield 57 57 - if is_blog_article? 58 58 %section.meta 59 59 %p ··· 108 108 109 109 / = safe_yield_content :footer 110 110 111 - = javascript_include_tag 'jquery-1.7.1.js' 111 + != javascript_include_tag 'jquery-1.7.1.js' 112 112 - code_mode = (current_page.data.code_mode || '').split(/\|/) 113 113 - if code_mode.include?('math') 114 - = javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML' 114 + != javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS-MML_HTMLorMML' 115 115 - if code_mode.include?('xypic') 116 116 :javascript 117 117 window.mathUseXypic = true; ··· 168 168 } 169 169 }); 170 170 - if code_mode.include?('lang') || code_mode.size == 0 171 - = javascript_include_tag 'highlight.pack.js' 171 + != javascript_include_tag 'highlight.pack.js' 172 172 :javascript 173 173 hljs.initHighlightingOnLoad(); 174 174 // $(document).ready(function() { ··· 179 179 // (function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src=("https:"===e.location.protocol?"https:":"http:")+'//cdn.mxpnl.com/libs/mixpanel-2.2.min.js';f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f);b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!== typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");for(g=0;g<i.length;g++)f(c,i[g]); b._i.push([a,e,d])};b.__SV=1.2}})(document,window.mixpanel||[]); mixpanel.init("eda89891866a7e90b6699df21e79ea61"); 180 180 // mixpanel.track("visit"); 181 181 /! end Mixpanel 182 - = safe_yield_content :scripts 182 + != safe_yield_content :scripts
+1 -1
source/stylesheets/blog.css.scss
··· 73 73 74 74 // From https://github.com/primer/markdown/blob/master/components/markdown.scss 75 75 // TODO: should use gem or bower 76 - @import 'vendor/primer-markdown'; 76 + @import 'vendor/primer-markdown.css.scss'; 77 77 78 78 // Overrides 79 79 .markdown-body {
source/stylesheets/vendor/primer-markdown.scss source/stylesheets/vendor/primer-markdown.css.scss
+2 -2
source/tech/calendar.haml source/tech/calendar.html.haml
··· 4 4 --- 5 5 -# coding: utf-8 6 6 %section.calendar 7 - - blog.articles.group_by {|a| "#{a.date.year}年" }.each do |year, year_articles| 7 + - section_articles.group_by {|a| "#{a.date.year}年" }.each do |year, year_articles| 8 8 %h2= year 9 9 - year_articles.group_by {|a| "#{a.date.month}月" }.each do |month, articles| 10 10 %div{:id => "calendar-#{month}" } ··· 13 13 - articles.sort_by { |a| a.source_file }.reverse.each do |article| 14 14 %li.listing-item 15 15 %time{:datetime => article.date}=article.date.strftime('%Y-%m-%d') 16 - %a{:href => article.url}=article.title 16 + %a{:href => article.url}=article.title
-43
source/tech/index.haml
··· 1 - --- 2 - title: Home 3 - blog: tech 4 - --- 5 - -# coding: utf-8 6 - - content_for :head do 7 - %title Utensil on Github 8 - /[if lt IE 9] 9 - <link href="http://fonts.googleapis.com/css?family=Amaranth:400,700" rel="stylesheet" type="text/css" /> 10 - <link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'> 11 - = stylesheet_link_tag "index.css" 12 - = stylesheet_link_tag "fonts/Amaranth.css" 13 - = stylesheet_link_tag "fonts/PT-Mono.css" 14 - = stylesheet_link_tag "tipTip.css" 15 - = stylesheet_link_tag "jquery-github-widget-default-theme.css" 16 - 17 - %h1.title< 18 - Uten 19 - %span.fork-me-before<> 20 - sil 21 - %a{:href => "https://github.com/utensil", :target => "_blank"} 22 - %img.fork-me-overlay{:src => "../images/fork.png"}/ 23 - %h2.subtitle 24 - %p 25 - %span In fascination of 26 - = succeed "," do 27 - %span.main-idea creating worlds by words 28 - %p 29 - %span and in pursuit of 30 - = succeed "." do 31 - %span.main-idea words behind the world 32 - %p 33 - %span 对 34 - = succeed "" do 35 - %span.main-idea 用语句构建世界 36 - %span 的迷恋, 37 - %p 38 - %span 以及对 39 - = succeed "" do 40 - %span.main-idea 世界背后的话语 41 - %span 的追索。 42 - 43 -
+41
source/tech/index.html.haml
··· 1 + --- 2 + title: Home 3 + blog: tech 4 + --- 5 + -# coding: utf-8 6 + - content_for :head do 7 + %title Utensil on Github 8 + /[if lt IE 9] 9 + <link href="http://fonts.googleapis.com/css?family=Amaranth:400,700" rel="stylesheet" type="text/css" /> 10 + <link href='http://fonts.googleapis.com/css?family=PT+Mono' rel='stylesheet' type='text/css'> 11 + != stylesheet_link_tag "index.css" 12 + != stylesheet_link_tag "fonts/Amaranth.css" 13 + != stylesheet_link_tag "fonts/PT-Mono.css" 14 + != stylesheet_link_tag "tipTip.css" 15 + != stylesheet_link_tag "jquery-github-widget-default-theme.css" 16 + 17 + %h1.title< 18 + Uten 19 + %span.fork-me-before<> 20 + sil 21 + %a{:href => "https://github.com/utensil", :target => "_blank"} 22 + %img.fork-me-overlay{:src => "../images/fork.png"}/ 23 + %h2.subtitle 24 + %p 25 + %span In fascination of 26 + %span.main-idea creating worlds by words 27 + = "," 28 + %p 29 + %span and in pursuit of 30 + %span.main-idea words behind the world 31 + = "." 32 + %p 33 + %span 对 34 + %span.main-idea 用语句构建世界 35 + %span 的迷恋, 36 + %p 37 + %span 以及对 38 + %span.main-idea 世界背后的话语 39 + %span 的追索。 40 + 41 +
+4 -4
source/tech/tags.haml source/tech/tags.html.haml
··· 5 5 -# coding: utf-8 6 6 %section.tags 7 7 #tag_cloud 8 - - blog.tags.each.sort_by{|tag, articles| -articles.size }.each do |tag_and_articles| 8 + - section_tags.each do |tag_and_articles| 9 9 - tag = tag_and_articles[0] 10 10 - articles = tag_and_articles[1] 11 11 %div{:id => "tag-#{tag}" } ··· 20 20 -# %backquote 21 21 -# = article.summary 22 22 - content_for :head do 23 - = stylesheet_link_tag "jqcloud.css" 23 + != stylesheet_link_tag "jqcloud.css" 24 24 - content_for :scripts do 25 - = javascript_include_tag "jqcloud-1.0.1.js" 26 - = javascript_include_tag "tags.js" 25 + != javascript_include_tag "jqcloud-1.0.1.js" 26 + != javascript_include_tag "tags.js"
source/writings/about.md source/writings/about.html.md
+2 -2
source/writings/calendar.haml source/writings/calendar.html.haml
··· 4 4 --- 5 5 -# coding: utf-8 6 6 %section.calendar 7 - - blog.articles.group_by {|a| "#{a.date.year}年" }.each do |year, year_articles| 7 + - section_articles.group_by {|a| "#{a.date.year}年" }.each do |year, year_articles| 8 8 %h2= year 9 9 - year_articles.group_by {|a| "#{a.date.month}月" }.each do |month, articles| 10 10 %div{:id => "calendar-#{month}" } ··· 13 13 - articles.sort_by { |a| a.source_file }.reverse.each do |article| 14 14 %li.listing-item 15 15 %time{:datetime => article.date}=article.date.strftime('%Y-%m-%d') 16 - %a{:href => article.url}=article.title 16 + %a{:href => article.url}=article.title
-13
source/writings/index.haml
··· 1 - --- 2 - title: Home 3 - blog: writings 4 - --- 5 - -# coding: utf-8 6 - %section.calendar 7 - - blog.articles.sort_by { |a| a.source_file }.reverse.each do |article| 8 - .post 9 - %h2 10 - %a{:href => article.url} 11 - =article.data['title'] 12 - %div 13 - =article.app.render_template(article.source_file)
+13
source/writings/index.html.haml
··· 1 + --- 2 + title: Home 3 + blog: writings 4 + --- 5 + -# coding: utf-8 6 + %section.calendar 7 + - section_articles.each do |article| 8 + .post 9 + %h2 10 + %a{:href => article.url} 11 + =article.data['title'] 12 + %div 13 + != article_body(article)
+5 -5
source/writings/tags.haml source/writings/tags.html.haml
··· 5 5 -# coding: utf-8 6 6 %section.tags 7 7 #tag_cloud 8 - - blog.tags.each.sort_by{|tag, articles| -articles.size }.each do |tag_and_articles| 8 + - section_tags.each do |tag_and_articles| 9 9 - tag = tag_and_articles[0] 10 10 - articles = tag_and_articles[1] 11 11 %div{:id => "tag-#{tag}" } ··· 18 18 %a{:href => article.url} 19 19 =article.data['title'] 20 20 %div 21 - =article.app.render_template(article.source_file) 21 + != article_body(article) 22 22 -# %li.listing-item 23 23 -# %time{:datetime => article.date}=article.date.strftime('%Y-%m-%d') 24 24 -# %a{:href => article.url}=article.title ··· 26 26 -# %backquote 27 27 -# = article.summary 28 28 - content_for :head do 29 - = stylesheet_link_tag "jqcloud.css" 29 + != stylesheet_link_tag "jqcloud.css" 30 30 - content_for :scripts do 31 - = javascript_include_tag "jqcloud-1.0.1.js" 32 - = javascript_include_tag "tags.js" 31 + != javascript_include_tag "jqcloud-1.0.1.js" 32 + != javascript_include_tag "tags.js"
+35
util/verify_middleman_rack_routes.rb
··· 1 + # frozen_string_literal: true 2 + 3 + require 'rack/mock' 4 + require 'middleman/rack' 5 + require_relative 'verify_middleman_routes' 6 + 7 + rack = Rack::MockRequest.new(Middleman.server) 8 + failures = [] 9 + 10 + ROUTES.each do |path, terms| 11 + response = rack.get(path) 12 + body = response.body.to_s 13 + body.force_encoding('UTF-8') 14 + 15 + failures << "#{path}: expected 200, got #{response.status}" unless response.status == 200 16 + unless response['content-type'].to_s.include?('text/html') 17 + failures << "#{path}: expected text/html, got #{response['content-type'].inspect}" 18 + end 19 + failures << "#{path}: response body is not valid UTF-8" unless body.valid_encoding? 20 + terms.each do |term| 21 + failures << "#{path}: missing #{term.inspect}" unless body.include?(term) 22 + end 23 + ESCAPED_HTML_MARKERS.each do |marker| 24 + failures << "#{path}: contains escaped HTML marker #{marker.inspect}" if body.include?(marker) 25 + end 26 + 27 + puts "#{path} #{response.status} #{response['content-type']}" 28 + end 29 + 30 + if failures.any? 31 + warn failures.join("\n") 32 + exit 1 33 + end 34 + 35 + puts "Verified #{ROUTES.size} routes through Middleman Rack app"
+61
util/verify_middleman_routes.rb
··· 1 + # frozen_string_literal: true 2 + 3 + require 'net/http' 4 + require 'uri' 5 + 6 + BASE_URL = URI(ARGV.fetch(0, 'http://127.0.0.1:4567')) 7 + 8 + ROUTES = { 9 + '/' => [], 10 + '/tech/' => [], 11 + '/tech/calendar.html' => ['Bourbaki', '近来的技术兴趣', '代码之美'], 12 + '/tech/tags.html' => ['Bourbaki', '近来的技术兴趣', '代码之美'], 13 + '/tech/2020/09/12/19-45-bourbaki-clifford-algebra-0901b.html' => ['Bourbaki'], 14 + '/tech/2013/05/18/recent-tech-interests-01.html' => ['近来的技术兴趣'], 15 + '/tech/2009/04/21/notes-on-beautiful-code.html' => ['代码之美'], 16 + '/writings/' => ['返初', '抵达', '父母'], 17 + '/writings/calendar.html' => ['返初', '抵达', '父母'], 18 + '/writings/tags.html' => ['返初', '抵达', '父母'], 19 + '/writings/2023/10/05/21-06-fan-chu.html' => ['返初', '林错风穿逡巡雁'], 20 + '/writings/2021/09/19/12-10-di-da.html' => ['抵达'], 21 + '/writings/2018/05/20/22-09-fu-mu.html' => ['父母'], 22 + '/blogs/' => ['On Love', 'Doomsday'], 23 + '/blogs/calendar.html' => ['On Love', 'Doomsday'], 24 + '/blogs/tags.html' => [], 25 + '/blogs/2016/06/09/on-love-in-the-context-of-super-ai.html' => ['On Love'], 26 + '/blogs/2016/05/20/on-tech-dev-and-doomsday.html' => ['Doomsday'] 27 + }.freeze 28 + 29 + ESCAPED_HTML_MARKERS = ['&lt;link', '&lt;section', '&lt;p&gt;', '&lt;article'].freeze 30 + 31 + if $PROGRAM_NAME == __FILE__ 32 + failures = [] 33 + 34 + ROUTES.each do |path, terms| 35 + uri = BASE_URL + path 36 + response = Net::HTTP.get_response(uri) 37 + body = response.body.to_s 38 + body.force_encoding('UTF-8') 39 + 40 + failures << "#{path}: expected 200, got #{response.code}" unless response.code == '200' 41 + unless response['content-type'].to_s.include?('text/html') 42 + failures << "#{path}: expected text/html, got #{response['content-type'].inspect}" 43 + end 44 + failures << "#{path}: response body is not valid UTF-8" unless body.valid_encoding? 45 + terms.each do |term| 46 + failures << "#{path}: missing #{term.inspect}" unless body.include?(term) 47 + end 48 + ESCAPED_HTML_MARKERS.each do |marker| 49 + failures << "#{path}: contains escaped HTML marker #{marker.inspect}" if body.include?(marker) 50 + end 51 + 52 + puts "#{path} #{response.code} #{response['content-type']}" 53 + end 54 + 55 + if failures.any? 56 + warn failures.join("\n") 57 + exit 1 58 + end 59 + 60 + puts "Verified #{ROUTES.size} routes at #{BASE_URL}" 61 + end