阅读视图

发现新文章,点击刷新页面。
🔲 ☆

Mitmproxy and iOS simulator

之前(兩三年前了)因為工作需求,想要確認 iOS 到底有沒有認真看待 HTTP cache 機制,因為在 app 內,收到的 HTTP status code 總是 200,然後我又看不到 request header,遠端的資料放 CDN 上也不好看到紀錄,轉念一想,我是不是可以改成監看 iOS 模擬器的所有請求呢?

搜尋之後發現有人說可以用 mitmoroxy,是開源的不像其他 proxy 除錯工具一樣需要付費,稍微測試了一下,發現這東西很好安裝和使用啊,所以花了一點時間研究看看是不是能達到目標,大概步驟如下:

  • 安裝 brew install mitmproxy
  • 然後開 iOS 模擬器
  • 安裝 mitmoroxy 的 cert 到模擬器裡面
xcrun simctl keychain booted add-root-cert ~/.mitmproxy/mitmproxy-ca-cert.pem
  • 啟動 mitmproxy
  • 然後設定你的 MacOS 網路來使用這個 proxy(預設是 http://localhost:8080),因為 iOS 模擬器和 host OS 是共用網路的

就這麼簡單,不過這方法還是有些限制,像是如果有用 HTTPS pinning 的話,那就還要其它設定;然後 mitmproxy 本身的操作很好上手,這邊就不多花時間說明了。

然後回到一開始的問題,到底 304 有沒有用呢?我這邊是用 React Native 內的 fetch,然後結論就是,在 mitmproxy 確實是看的到 304,不過在 RN 的 context 內就會變成 200 了,其實後來想想也覺得合理,因為應用程式層本來就不應該去處理 HTTP 層的 cache 問題,這樣大大的簡化了複雜度。

參考:

🔲 ☆

Unicode CLDR 與貨幣數值格式

Venezia

其實一直以來都有點好奇,像 Intl 這種可以根據語系格式化輸出數字、貨幣數值或是日期等資料的工具函數,它的資料集到底是哪裡來的?會很好奇是因為這其實是一個多對多的組合,不同的語言地區配上不同的貨幣,算起來每種資料格式都要維護一組數量不小的組合,例如我想要用法文或英文顯示 10000 新台幣要用怎麼顯示呢:

// zh-Hant
$10,000.00
// fr
10 000,00 TWD
// en-US
NT$10,000.00

可以看到有很多點不一樣,首先數字格式的部分,可以看到小數點符號、千位數的分隔符號都不一樣;然後是貨幣符號,可能放前面可能放後面,中間可能會有空白(而且是 NBSP),然後根據不同組合可能會用短的貨幣符號,也可能用長的或是完整的貨幣代碼。作為比較,同樣的三組語系,如果改成顯示歐元則是:

// zh-Hant
€10,000.00
// fr
10 000,00 €
// en-US
€10,000.00

可以明顯看到,相同的語系顯示不同的貨幣數值,也有不一樣的格式設定,證實了它確實是一個多對多的關係,現在 ISO-639 有規範到的語言有 183 個,ISO-3166 的國家則是 271 個,相乘起來將近五萬種組合的資料是怎樣維護的呢?結果,其實這些資料的定義和管理都是在 Unicode 的 CLDR 專案,CLDR 是 Common Locale Data Repository 的縮寫,收集整理了各種因為地區不同而有差異的資料格式,除了上面提到的貨幣、數字之外,還有像是日期、時間、度量衡、數字、姓名(姓前面還名前面、有沒有中間名等)等的格式,然後還有像是國家、貨幣、時區、單位甚至是 emoji 的翻譯。

CLDR 網站上可以直接看到這些資料,拿繁體中文為例,網頁位置在 charts 下,下面的圖是第 44 版的,最新的版本其實是 48,以下請見截圖介紹,最右邊都有值的那欄就是 zh-Hant 繁體中文的翻譯和格式(pattern)。

國家名稱(這邊用的單字其實是 territory,翻譯通常是領土、疆域)、語言和時區:

CLDR 44 zh-Hant Country CLDR 44 zh-Hant Language CLDR 44 zh-Hant Timezone

日期時間格式:

CLDR 44 zh-Hant Date Time

也有特定國家用的系統,像是中國的天干地支和二十四節氣:

CLDR 44 zh-Hant Chinese Time and Season

日本的年號:

CLDR 44 zh-Hant Japan Era

這篇所提到的數字格式和貨幣顯示方式:

CLDR 44 zh-Hant Number

貨幣名稱:

CLDR 44 zh-Hant Currency

可以看到以上這些資訊都有繁體中文的文字翻譯,所以其實這都可以當成正式的譯名了。

這些資料的原始格式都是用 XML 維護的,東西放在 GitHub 上,例如我們上面舉例的 zh-Hant 的檔案就在這,有興趣的可以看看檔案結構長怎樣,去上一層目錄則可以看到所有目前有存在的地區語言組合(語系、locale),目前有在維護的是 1127 種,超過一千個檔案所以其實在 GitHub 的網站上也不會全部列出來,而這一千多種語系其實遠大於我一開始提到的 ISO-639 規範到的一百多個語言,所以實際有在維護的資料數量比我一開始隨手估計的還要大上六七倍。

回到檔案內容,有兩個字元想要特別介紹的,這種用字元表示特別意義的方法在其他地方蠻少見,真不愧是 Unicode 專案:第一個是 ↑↑↑,可以在很多地方看到,這三個字元出現的話,就是代表請找 fallback 值,一般而言就是把語系的值拆分扣掉最後面那一段,如果在查找的時候收到的語系是 zh-Hant-TW,那第一次 fallback 就會發生在找不到該檔案,改成找 zh-Hant 的檔案,也就是上面範例那個檔案,找到檔案後,查找該檔案內的指定的定義,結果定義是 ↑↑↑ 時,就改成去找 zh 的檔案內的定義,如果一直都找不到就會去 root.xml 找。

第二個要介紹的則是 ¤ 字元,這是我第一次注意到這個字元,本來以為是比較新的定義,不過其實它是很古老的字元,根據 Wikipedia,它在電腦領域最早出現是在 1972,7 bit 編碼時就有了,比我還老,一開始就是作為貨幣符號的占位符號使用,不代表任一特定的貨幣,那這個符號在 CLDR 這邊是怎樣用的呢?在 zh-Hant.xml 檔案內直接搜尋該字元,就可以看到這段定義:

<currencyFormat type="accounting">
	<pattern>¤#,##0.00</pattern>
	<pattern alt="alphaNextToNumber">↑↑↑</pattern>
	<pattern alt="noCurrency">↑↑↑</pattern>
</currencyFormat>

其中的 <pattern> 內的值就是 CLDR 自己定義的數字、貨幣的顯示格式的 pattern(格式),詳細可以參考官網的介紹,每個字元都有其定義,而不是真的用那個字元顯示,例如 0 代表一定要出現的位數,但是數字系統可以換,所以最後輸出不一定是阿拉伯數字;, 代表的是千位數分隔符號的位置,實際上要用哪個字元作為分隔符號,則是看該語系的定義;同理,¤ 字元的用途就是在這個 pattern 當中,貨幣符號的放置位置,而要顯示怎樣的貨幣符號,則是還要看語系和設定,例如新台幣在 zh-Hant 中的定義就有以下幾種:

<currency type="TWD">
	<displayName>新台幣</displayName>
	<displayName count="other">↑↑↑</displayName>
	<symbol>$</symbol>
	<symbol alt="formal">NT$</symbol>
	<symbol alt="narrow">↑↑↑</symbol>
</currency>

然後在其他語系可能還有直接使用 currency code 的,所以至少就有四種,而根據 LDML(這份 zh-Hant.xml 文件的格式),其實可以根據這個 ¤ 字元重複的次數,來決定要如何顯示該貨幣符號,詳見下表:

LDML currency symbol

不過其實在 zh-Hant.xml 當中,搜尋到的所有的貨幣數值的 pattern,都只有一個 ¤,所以理論上應該都是一樣的用 standard currency symbol,但是實務上似乎比較少真的直接用到這特性,而是透過設定更改的比較多,在 JavaScript 的 Intl.NumberFormat 的 style option 中有一個 currencyDisplay 的設定可以用來改變貨幣符號的顯示方式,有 codesymbolnarrowSymbolname 這四種,並沒有用到不同數量的 ¤ 的 pattern。深究其原理,其實 Intl.NumberFormat 底層就是 Unicode 官方的 ICU,而 ICU 則是透過 Unit Width 這個選項來調整,實作似乎是在替換時根據不同的 unit width 選用不同的值,而不是修改 pattern。而 Intl.NumberFormat 也就是透過設定 Unit Width 來達成的,結果就是,如果沒有直接使用 ICU 手動設定 pattern,似乎是不會真的用到多個 ¤ 的模式,不過這其實也太細節了,我也不是非常熟悉,所以只能說個大概。

最後想介紹的,就是 CLDR 其實還提供了不少的補充資料(supplemental),舉幾個比較有趣的:

🔲 ☆

2024 北海道 Part 2

北見神社

前篇,第五天一早就是先去地獄谷周遊一下:

登別地獄谷 登別地獄谷

然後就出發前往今天的目標帶廣了,有點概念的就知道這距離很遠,這一天也是我這趟要開最久的一天,所以是午餐前就出發了,午餐是中途下高速高路找的一間在荒野中的拉麵店:MACHIHAZURE T&F」,評分還不差而且真的也還不錯吃,位置其實比較靠近新千歲,因為繼續往東前進就會好一大片都是未開發的地方了。

MACHIHAZURE T&F 北海道

到帶廣後的第一站就是六花亭本店了,特別來就是為了去二樓的咖啡廳吃甜點。

六花亭 六花亭

六花亭本店的商品超級多,拍了一大堆之前沒看過的東西,像是洋芋片,冷藏商品,還有很好笑的紀念品等:

六花亭 六花亭 六花亭

第五天晚上住的是離市區十分距離的十勝川温泉 観月苑,一泊二食加上各室溫泉,泉質我很喜歡(美人湯、弱鹼性、水呈黑色、泡完滑滑的),面十勝川的風景也不錯,加上餐點也蠻好吃的,而且還有煎過的干貝,在北海道要吃到有調理過的干貝真的是太難了!總之這天的住宿體驗是非常好的。

十勝川温泉 観月苑 十勝川温泉 観月苑 十勝川温泉 観月苑 十勝川温泉 観月苑 十勝川温泉 観月苑

第六天早上就是去帶廣神社和車站附近逛逛加午餐,在帶廣神社才發現他們北海道有神社的聯合籤叫えぞみくじ(蝦夷御籤),每個神社都有他不同造型的籤可以代回家作紀念,帶廣的是「魔鮭福鱒」!

帶廣神社 帶廣神社 帶廣神社

午餐則是吃車站附近有名的豚丼:豚丼のぶたはげ

豚丼のぶたはげ

飯後就開始繼續往東了,這一天的目標是阿寒湖,不過半路開始天氣就變差了,接下來幾天也都不再是藍天白雲的好天氣了。

阿寒湖

阿寒湖溫泉街那邊就開始會看到野生動物了,這一天就看到兩次:

阿寒湖 阿寒湖

晚餐也是找街道上的餐廳,分數還不錯的 味心,運氣不錯坐到最後一桌,後面還有客人老闆就說滿席了,然後才發現這些比較小的日本餐廳好像不太會說還要等多久,而是直接說沒位子了

味心 味心

晚飯後去了 KAMUY LUMINA,很特別的體驗,但是環境是超級低光所以沒什麼照片,有機會的話值得參加一次:

KAMUY LUMINA KAMUY LUMINA

隔天早上一早就去搭遊湖的船,然後逛了下愛奴文化傳承創造館,在阿寒湖アイヌコタン的商店買了紀念品後,就離開繼續往東移動,這一天的目標是這次旅程的最東端:摩周湖,看到照片的時候就超級想來的,結果天數夠就安排下去,午餐是先到摩周車站前的食堂と喫茶 poppotei,是小有名氣的店,餐點也都蠻好吃的,在這邊我們還有遇到台灣來騎腳踏車的團客,有保母車還有預約餐廳這樣,之前比較沒接觸過,不過好像蠻多人會去日本這樣騎行挑戰的。

食堂と喫茶 poppotei 食堂と喫茶 poppotei

飯後,終於要前往此行中我最期待的摩周湖了,真的像是在夢中一樣:

摩周湖 摩周湖

大概和我十多年前去到千圓鈔票拍攝的地點一樣夢幻吧...

總之,就只能繼續行程,往北去網走了,網走真的是氣溫特別低,這一天線跑去網走神社買えぞみくじ,這邊的是可愛的雪天使:

網走神社

這天晚餐也是沒安排,本來想說去超市買東西吃就好,結果走著走著經過一間網走啤酒的燒肉店好像超吸引人,可是完全沒位子,真是可惜,有安排來網走的人可以考慮定個位。

網走

隔天早上的行程就是定番的博物館網走監獄了,我當然是因為黃金神威的關係,不過來之前就聽說小朋友會很喜歡,結果,沒想到,是真的!!!我到現在還是不理解。

博物館網走監獄 博物館網走監獄 博物館網走監獄

逃獄王白鳥由榮

博物館網走監獄 博物館網走監獄 博物館網走監獄

離開監獄博物館後,就要開始往西回札幌方向了,往西回程的第一站是旭川,這一天也是要開車很久,不過還特別有繞去北見神社買えぞみくじ,到旭川後先跑去 BigBan 二手店逛一下,超大,照片都看不到另外一頭了。

Recycle shop Bigban Asahikawa Miyamae Shop

還有很多漫畫二手書,可惜我現在實體書買很少了:

Recycle shop Bigban Asahikawa Miyamae Shop Recycle shop Bigban Asahikawa Miyamae Shop Recycle shop Bigban Asahikawa Miyamae Shop

然後第八天晚上是住旭川JR酒店,這間也是很方便,一樓就是 AEON 超市,只是我那天沒注意到有超市,而且因為 AEON 商場營業到晚上九點的關係就急著隨便吃了晚餐,但是其實一樓的 AEON 超市有到晚上十點,如果有先搞清楚就會直接去超市就會改變一下行程了,不過可能變成兩餐都吃超市。

旭川JR酒店 旭川JR酒店

超市蠻好逛的,整面的果醬:

AEON 旭川站前店 AEON 旭川站前店

有經過本店但是沒進去的柳月(不過有在小樽的店光顧吃冰):

AEON 旭川站前店

第九天開始請見 [Part 3][part-3]

[part-3]"https://blog.othree.net/log/2025/12/06/2024-hokkaido-3/

🔲 ☆

2024 北海道 Part 1

Lake Hill Farm

去年安排了一趟北海道的旅行,主要的目標是吃吃,沒有特別想獨立抽出來的分享的部分,所以就分幾篇貼照片加流水帳紀錄一下吧。行程一開始的規劃大致上如下:

Day # Trip 
16  1 小樽
17  2 小樽
18  3 洞爺湖
19  4 登別
20  5 十勝川温泉
21  6 阿寒湖
22  7 網走
23  8 旭川
24  9 富良野
25 10 札幌
26 11 札幌
27 12 札幌
28 13 札幌
29 14 家

基本流程就是新千歲進出,第一天到機場後直接火車搭到小樽,然後在那邊住兩晚後租車開始繞一圈,最後回到札幌還車,然後三四天市區行程,最後一天就去機場。接下來就來介紹這趟旅程吧:

第一天到新千歲機場後,稍事整理之後,就去搭乘函館本線直奔小樽,過札幌之後火車路線基本上是很靠近海邊的,中間還經過一個朝里站,車站本身古色古香之外,海景也很不錯,而且我還發現有些日本人特別在這站下車,回來查了一下,果然是個小有名氣的車站,冬天看起來很漂亮,不過我們搬著行李也不可能跑下去,所以我就是特別拍下車站名稱而已:

北海道 朝里

然後之後就到達小樽了,其實我上次大約十年前來北海道時,就有來小樽,當時是和我媽跟團,雖然停留時間沒很久但是就已經很喜歡這邊了,所以這次特別安排在這邊住兩天,還住比較貴的 Nord 小樽酒店運河側房間。照片的小樽車站是晚上拍的,到達時天還沒黑:

小樽市

運河旁的 Nord 酒店,很顯眼:

Nord 小樽酒店 Nord 小樽酒店

Nord 小樽酒店位置很好,車站走的到的位置,又在運河出名那一個區段的其中一邊的大路口,不過河加海景沒有讓人很驚艷到,加上這幾天的活動路線都會在晚上跑去車站對面的唐吉訶德,後來覺得其實住在車站對面的 Dormy Inn 似乎也不錯。

第一天沒去有名的堺町通り商店街,就是附近簡單繞繞,去找晚餐而已,晚餐就吃有名的若鶏時代 なると 本店

若鶏時代 なると 本店 若鶏時代 なると 本店

食物還不差,可以體驗看看,小可惜是當時不知道他們有自己的可樂,好像也是名物。飯後就去唐吉訶德逛了一下然後回飯店睡覺,接著隔天早餐,其實應該說這兩天的早餐都在 Komeda 咖啡解決的:

小樽市 小樽市

在店內還翻到一本雜誌介紹了東京迪士尼樂園的票價變化:

Tokyo Disney Land Ticket Price

吃完早餐後就去旁邊從倉庫改成的小樽市総合博物館 運河館參觀,這博物館的主題很明確,就是介紹小樽市的歷史和週邊的生態,參觀後才知道其實小樽是北海道開發初期時重要的港口,運河就是當時為了運貨而修建的,可以看到很多歷史資料、地圖、文物等:

小樽市総合博物館 運河館 小樽市総合博物館 運河館

博物館外觀,靠近這一半邊現在沒使用,中間紅磚的是商店,博物館是比較遠的那一半:

小樽市 小樽市

還有就是在北海道真的很容易看到黃金神威的海報:

小樽市総合博物館 運河館

接著就去運河和小樽堺町通り商店街了:

小樽運河 LeTAO

堺町通是我上次就非常喜歡的點,只是那時候跟團,時間很短,根本無法好好逛,只有逛了六花亭、音樂盒和北一硝子,這次終於可以慢慢的從頭走到尾了,非常開心。

小樽堺町通り商店街 小樽堺町通り商店街

這次沒吃到的雪印パーラー:

小樽市

午餐的万次郎:

万次郎 万次郎 万次郎

各個漂亮的建築:

小樽市 LeTAO 北菓楼 小樽堺町通り商店街 小樽堺町通り商店街 小樽堺町通り商店街

之後走回旅館休息一陣子後,晚餐出去覓食,途中不小心經過北海道毛巾株式會社,一下子就買了好幾千日幣

北海道タオル株式會社 北海道タオル株式會社

晚餐吃屋台村紅磚橫丁炭す Grill

炭すグリル 炭すグリル 炭すグリル

然後一樣亂逛,去唐吉珂德後就回旅館了:

小樽都通り商店街 小樽都通り商店街

地方的動漫畫專門店:

小樽都通り商店街

第三天早上就要去租車開始移動了,本日目標是早上去余市酒廠、然後下午去洞爺湖那邊,晚上就是住在洞爺湖,余市酒廠因為沒有預約到參觀導覽,所以只能去後面的商店和博物館,結果因為不熟跑去正門,找停車位時發現旁邊旁邊有余市宇宙紀念館,剛好也在他們的休息站旁邊,這個休息站超小的名稱很特別叫: 道の駅 スペース・アップルよいち (太空蘋果)。

余市宇宙紀念館 余市宇宙紀念館

小孩看到宇宙自然就不受控制,結果花了一個多小時在裡面,展品沒特別亮眼,但是打發小孩是蠻不錯的,會在這邊有一個宇宙紀念館,其實是因為日本第一次上太空的太空人之一的毛利衛是余市出身的,所以比較像是地方的資金營運的,很多展品是手工製作的,一年還有三次特別的紙模型製作教學活動。

參觀完宇宙紀念館,因為已經中午就先跑去吃午餐了,吃的是柿崎商店 海鮮工房的海膽,可以看到我那碗要 4320+580JPY,其實單價還是不低,只是在台灣要吃到這樣的只會更貴,甚至是吃不到,所以還是吃下去了。

柿崎商店 海鮮工房 柿崎商店 海鮮工房

飯後在樓下商店逛一逛,然後就到余市酒廠的博物館和商店,買了些工廠限定的商品和酒回去當伴手禮:

余市蒸餾所 余市蒸餾所

接著就往第三天的目標洞爺湖前進了,途中特別小繞去「羊蹄のふきだし湧水」裝了些水。

羊蹄のふきだし湧水

這一天住的是在山上的 Hotel COCOA,風景很好但是一定要自駕才到的了,從溫泉街開上來大概要十五分,不過是全山路,我們有先跑去溫泉街那邊晚餐還有散步,太陽下山了才移動回來,日本的山路幾乎都沒路燈,雖然不是第一次開日本郊區的路,但還是真的蠻可怕,奉勸大家日本自駕要盡量避免晚上在郊區移動。

洞爺湖溫泉街那邊勉強找到一間有營業的餐廳,然後看夕陽看湖,之後逛了乃之風的開放區域(商店很大),之後就摸黑開車回旅館,到房間還剛好可以看到煙火。

洞爺湖 洞爺湖 洞爺湖 洞爺湖 煙火

隔天早上天氣超好,去了 Lake Hill Farm 吃吃買買和休息,這個地點可以看到超大的羊蹄山,沒錯,就是羊蹄山戰鬼裡面的那座。

Lake Hill Farm Lake Hill Farm

之後去搭有珠山纜車,可以看到昭和新山的上面,從下面看很漂亮的山形,到上面一看就漏氣了:

有珠山纜車

我沒去找到可以拍完整洞爺湖的位置,不過去另外一邊可以看到隔海對面的景色也是很棒:

有珠山纜車

之後回了洞爺湖邊的 HLAHAL 吃湯咖哩,這間風景好而且食物又好吃,大推!

SoupCurry HLAHAL SoupCurry HLAHAL

飯後就出發前往第四天住的登別了,我們住的是登別第一滝本館,除了多種溫泉之外,還有游泳池可以讓小孩玩得很開心,而且裡面很大,到處逛逛也很有趣,後來晚餐也是在館內解決,其實本來是要吃溫泉街上的餐廳,但是只有一兩間而且剛好公休。

登別第一滝本館 登別第一滝本館

第五天開始請見 Part 2 (WIP)

🔲 ☆

HayatoS

HayatoS

不知不覺就要將近一年沒有發文章了,其實我自我認知是我進入了一個有點長的鬱期,加上還有很多其他事務把我的空閒時間都用掉了,結果就都沒花心思在這塊,連帶的去年和今年的兩趟日本的遊記都沒寫完,第二趟的照片連整理都沒有,技術文章也是一些題目都放著沒進展,其實我這些狀況還沒改變,但是今天還是鼓起動力寫了文章,因為最近有朋友驟逝

HayatoS

其實這一年身邊一直有些和死亡有牽連的消息和體驗,先是有一位朋友死門關前走了一遭,不過還好恢復很順利,不過我知道已經是事後了,而且他人不在台灣所以真的還沒什麼實感;接著在我暑假帶小孩出遊時,突然聽到在 HTC 時的前同事 Bingo 過世的消息,當下也是很震驚,我還記得共事時期他給人的形象是很健康開朗的陽光男孩,還是個會去衝浪的人,特別有印象的是有次我去日本買到了豐天商店的衣服,結果他看到超喜歡,後來自己去日本買了超多件,幾乎每天都穿不同款上班。

接著我自己健檢的時候因為要作腸鏡胃鏡,結果我脹氣加退麻醉痛苦了兩三天,我是屬於退麻醉會非常不舒服的人,不舒服到連滑手機都沒辦法,滑一下頭就痛起來;然後脹氣不舒服這件事,我覺得很多人可能沒體會過,其實是可以不舒服到讓人生不如死的,我就曾經一次脹氣整天不舒服到去急診,後來打針強迫腸胃蠕動,這次則是知道原因但是只能等時間過去,只是時間很長,這兩三天的時間我大概有點體會到那種重病末期痛苦無法緩解想要求死解脫的心情,只是因為我知道我還會恢復,所以還能撐下去。

順便宣導一下,千萬不要對嘴巴或肛門灌氣,真的很容易會死人的,新聞很多

然後就是最近的孩雅多學長過世的消息了,其實週一消息傳開當天我有點忙碌,不過還是看到兩位社團學長發了不知所以然的文,直到我當天忙的差不多才看到朋友轉貼 lordmi 的 plurk 文才知道,當下也是不敢相信,因為週末前我才回他的文,然後過了一個週末就跟我說他已經過世了...

Screenshot 2025-11-30 at 18-08-15 othree - Plurk

接下來兩天,我大概就是只要閒下來就會想到這件事情,然後過幾天就找找看手上有沒有以前拍到他的照片,結果意外的少,一個原因是因為他也是會拿著相機到處跑的人,而我和他共同會拿相機出現的場合其實不多,我算是他畢業後才開始有相機玩,而且那時我還不太會想到要幫攝影師拍照(後來在研討會擔任攝影紀錄時我就會加減幫其他攝影師或是工作人員拍照),最後挑了第一張照片出來。

因為他是在我認識的人當中,對遊戲的熱情最高的人,畢業後去遊戲公司,甚至在大學時他並不是程式人,但是現在卻已經可以擔任遊戲程式了,而且一直都很關注遊戲業界的發展,我一直都有在看他轉貼的遊戲新聞,所以這幾天到現在,只要有牽扯到遊戲,不管是新作上市,有趣的新聞,甚至是自己要開遊戲來玩,都會覺得無限惋惜。

剛好在那幾天,我在看縱使星辰殞落,妳仍在歌唱 這本小說,很巧也是講到死亡的事情,其實我以前是不太能理解為何有些人會想要在死前,在世界上留下自己的痕跡,經過這一年的洗禮下來我或許比較能體會了,至少我目前的想法是,因為死亡不可避免(扣除在追求永生的那些人),所以會想讓自己的存在以其他形式留存,不過認真說真的很難,人只要不在了,就算能在歷史上留名,那名字也不太會對正在活上是上的人們產生什麼影響力,甚至是親近的人也必須為了在世上活著而不斷的做著每天的工作,無法只沉浸在緬懷故人,其實就算扣除內容是牽扯到死亡這件事之外,其實這本書另外一個主軸我覺得他也會有興趣,算是個我有想推薦給他的小說,真的是太讓人惋惜了。

縱使星辰殞落,妳仍在歌唱

最後想說的是,其實是想給還不到 40 歲的人看的,不過不知道讀者群裡面有多少比例就是,總之,就是如果有人跟你說「過 40 開始身體會明顯變差,身邊有人會開始離開。」他們說的是真的!把握時光!保持健康!

🔲 ☆

Oklab Color Space

2019 年的時候,寫過一篇文章介紹了 Lab Gradient,然後就沒特別關注相關發展,直到前幾天看到勞哥的推文提到 Oklab 這個色彩空間,而且瀏覽器已經原生支援了,我才發現原來網路標準的發展有跟上來,我也趁機多惡補了一些相關的知識。

因為一些搜尋讓我今天才了解 oklch 這個色彩格式(或是色彩空間)的使用方法。這個色彩格式在 2023 年納入了幾乎所有現代瀏覽器,好奇查詢之下發現了作者的 blog 有寫為什麼要製作 Oklab 的原因與研究過程,以及詳細的討論過去 HSV 或 HSL 系的色彩空間到底有什麼問題,收穫滿滿。...

# -- 勞哥 maylogger (@may_logger) July 13, 2024

在介紹 Oklab 前,先來介紹以前提到的 Lab 吧,其實它是國際照明委員會(International Commission on Illumination,簡稱 CIE)在 1976 年提出的色彩空間定義,全名是 CIELAB color space,或是簡寫為 L*a*b*,多加 * 為了避免混淆,Lab 其實是不正確的縮寫,不過這三個字母其實就是該顏色空間的三個軸:L 代表亮度、a 代表紅色到綠色間的位置、b 代表藍色到黃色間的位置,也就是 opponent color theory(又稱對比色理論或色覺對向論)的顏色組成,這個色彩空間的重點在它的座標比較符合人類對色彩的感知。

Oklab 又是什麼呢?它是 Björn Ottosson 在 2020 年底發表的一個新的色彩空間定義,他在文章內有詳細的說明為什麼會想要定義一個新的色彩空間,文內也列舉了現存的色彩空間的主要問題,其中 CIELAB 的問題就是在 predict hue (預測色相)有些問題,尤其是藍色附近,其實我一開始對於這個 predict 感到很疑惑,想說到底是什麼意思,後來看到另外一篇文章 An interactive review of Oklab,文章一開始放的互動工具預設的漸層設定就是藍色到白色,然後一看就很明顯, CIELAB 的漸層色相跑一下就歪掉了變成偏紫色去了(random 按鈕可以按按看看其他色相都沒這樣嚴重),才了解到因為 CIELAB 是屬於人類感知的色彩空間,意思就是它的依歸其實是人類的感覺,所以需要從三維座標去推測人類實際上看到感覺到的顏色,數值上一樣的話就應該讓人感覺一致,而 Oklab 則是結構和 CIELAB 一樣,但是透過新的資料集來調整並解決前面提到的問題,而後在 2023,Oklab 進了 CSS Color Level 4 的草稿,主流瀏覽器現在也都已經支援。

CIELAB

進 CSS Color 代表什麼意思呢?第一個當然就是可以用 oklab() 函數來定義顏色了:

oklab(40.1% 0.1143 0.045);
oklab(59.69% 0.1007 0.1191);
oklab(59.69% 0.1007 0.1191 / 0.5);

除了直接定義顏色之外,現在 CSS 也支援相對顏色(relative color)了:

/* Relative values */
oklab(from green l a b / 0.5)
oklab(from #0000FF calc(l + 0.1) a b / calc(alpha * 0.9))
oklab(from hsl(180 100% 50%) calc(l - 0.1) a b)

這樣要只調整色相或是亮度都變得很簡單,或是也可以用 oklch(),這樣色相(Hue)就更好挑選。

然後就是漸層了,現在的 CSS 漸層也支援使用不同的顏色內差方式,也就是用不同色彩空間來算中間的顏色變化:

linear-gradient(in oklab, blue, red)
linear-gradient(in lab to right, #44C, #795)

在最前面加上 in <color-space> 就可以,支援的色彩空間其實不少,如果是線性漸層,那支援 srgb、srgb-linear、display-p3、a98-rgb、prophoto-rgb、rec2020、lab、oklab、xyz、xyz-d50、xyz-d65,如果是 polar 漸層,那支援 hsl、hwb、lch、oklch,其實相當夠用,而這段語法其實是叫 color-interpolate(顏色內插),除了漸層之外,會用到的地方還包括 filter、animation、transition 和 color-mix() 函數等。

前面也已經提到,現在主流瀏覽器都已經支援了,不過還是來看一下 caniuse 上的細節,Chrome 是 2022 就支援了,但是 Firefox 是到去年的 2023 才支援,如果要抓兩年的時間的話就還要再等等,當然現在也還是可以直接用,多加一組 fallback 就可以。

除了瀏覽器原生支援外,其實也不少其它開發相關的工具支援,也有不少文章在介紹,像是 Smashing Magazine 的 Falling For Oklch: A Love Story Of Color Spaces, Gamuts, And CSS 和 Evil Martians 的 OKLCH in CSS: why we moved from RGB and HSL,兩篇文章就介紹了不少工具和一些延伸的文章,工具部分像是 Figma 的 plugin OkColor 和 npm 上的 convert-to-oklch,Evil Martians 還做了一個 oklch.com ,是針對 Oklch 的 color picker 還蠻厲害的。

oklch.com

🔲 ⭐

看見不同的學習風景

SEE DIFFERENT 看見不同的學習風景

週末帶小孩去松山菸廠意外發現到「SEE DIFFERENT 看見不同的學習風景」這個展覽,心中實在是有些想法和感觸想分享,首先先來介紹一下這個展覽吧:這個展覽其實是「第二屆教科圖書設計獎」的得獎作品,沒錯,是教科書,國中國小的教科書的設計展!而且不只是視覺上的設計,評選的範圍也包含內容的設計,展場展出的就是本屆得獎的教科書們,有一整區是可以翻閱的,只能說現在的教科書和我接觸過的三十年前左右的真的是差很多,除了更加活潑有質感的設計,還有各種清晰的圖表輔助,甚至連內文都變得很好閱讀,很像是在看科普書而不是教科書,深入了解之後,才知道這一切其實要從十年前,也就是 2014 年在 FlyingV 上的「美感細胞的教科書改造計畫」開始,其實我當年也有看到,不過我是沒什麼參與,覺得就是很理想但是很難進入體制內,沒想到,美感細胞默默耕耘十年,加上教育部推動美感教育,還真的推展開來了,教科圖書設計獎都辦到了第二屆,而美感細胞在其中的角色,除了在 FlyingV 上三季的募資計畫,後來還成立社團法人,承接一些政府合作案之外,也持續進行相關研究,發佈了不少的設計報告和參考資料,另外還有一個很重要的角色,就是作為教科書出版社和設計師之間的媒合橋樑,其實教科書的出版不是那麼容易,和一般書籍比起來限制較多,除了內容要送審之外,教育部還有印製規定

SEE DIFFERENT 看見不同的學習風景

SEE DIFFERENT 看見不同的學習風景

SEE DIFFERENT 看見不同的學習風景

我確實以前也是認為台灣的美感素養真的差很多,而這在各種層面上展現,從平面設計開始像是文宣、廣告設計、然後一些政府機關的公文、表單的排版字體(看過數年前香港的報稅表單,排版和字體真的是比台灣好很多)等等,更進一步到店面、商場設計(像是台北車站站前地下街 K 區的前後對比:誠品 vs 東森)、道路規劃、建築設計、年末的燈飾、街景、古蹟打燈(像是以前台北郵局)等等。台灣一來普遍不重視美感和設計,二來是設計人材也少,尤其是公部門相關的東西更是慘烈,最常被人拿出來講的大概就是國慶典禮的主視覺設計了吧,這幾年的改變確實有目共睹,終於能夠脫離千篇一律的設計風格,然後我才慢慢了解到台灣其實不是沒有設計人材,而是主政者和業主不重視,甚至可能是根據種種不能直說的原因來挑選廠商,當然這也造成了惡性循環,業主不重視、設計師沒案子、願意投入設計領域的人就少;美感細胞的三位創辦人張柏韋、林宗諺和陳慕天在十年前的教科書改造計畫第一季其實就有見到這個問題,見到這個問題的人其實應該不少,但是真的有想面對它處理它的人就少之又少,更何況三人還不是設計相關領域、還在體制之外、當時也還只是大學畢業生,實在相當讓人佩服。

另一個感觸則是體制外到體制內這件事,沒想到在這幾年內可以看到兩件事情真的這樣發生,真的是要感謝現在的主政者願意沒事找事作,這邊提到的教科書質的改變是一個,當然這只是一個手段,真正想要改變的是整體國民的美學素養,這還需要很長時間的發酵;另外一個體制外到體制內的改變,則是報稅軟體,相信這就是大家都有目共睹的了,最早是設計師卓致遠在 Join 平台上提出的,財政部注意到這個問題後也非常重視且積極,才推動了報稅軟體整個大改變,提案人卓致遠當然也不是起個頭就跑走,他也是很積極的參與協助設計改善,一些過程可以參考雨蒼在 2018 年寫的「新版報稅網站是怎麼煉成的?」,唐鳳也在其中出了些力協助溝通,當年她還是政務委員,數位發展部是到 2022 年才成立的,當然數發部的貢獻在基礎建設,所以一些新的認證方式應該也是有其貢獻才得以實現。

美感細胞  研究報告

然後另外想提的是,美感細胞的那些研究報告內容其實都蠻不錯的,像我主業是前端工程師,但是也一直對平面設計、字體、文字排版等有些興趣,所以這些報告當中的教育字體應用指南敎科書印製規格提議報吿易讀設計指南 Guidebook教材通用色彩應用指南四份我都有看過一遍,內容都蠻不錯的,都從問題和背景開始就做了很詳細的介紹,報告本身的編排和一些輔助的圖表也都弄的很清楚,可以看得出來花了不少心力要讓報告本身可以自證其述(self-hosting?);另外還有一本在會場有展出的「翻開下一頁➝NEXT PAGE教科書風格創新趨勢研究探討」,則是以教科書近年來的變化為主題,還介紹了第一屆的教科圖書設計獎的得獎作品,這本的出版則是台灣設計研究院,也就是展覽的主辦單位,不想下載的話其實以上這幾本也都有放到 issuu 平台上,可以參考以下連結:

最後補一個 中央社 文化+ 的專題報導「聽說課本不一樣」,還有這次展覽我最喜歡的教科書封面:

SEE DIFFERENT 看見不同的學習風景

🔲 ☆

時間ねぇ

時間のないサイト運営者リング

在 blog 這詞最為蓬勃之時,很流行在自己的網站上放各式各樣的 banner,這些 banner 種類用途很多,像是顯示你網站使用了甚麼技術、你想幫忙宣傳的東西、網站連結、甚至是一些自我的主張表現或是可以稱為無用小廢物(像是日本放置協会,又簡寫為 NHK)的都有,我以前也放了不少,不過最後留下來的就只有兩個,第一個是 MDN 的推廣貼紙,第二個則是「時間のないサイト運営者リング」,沒時間的站長串連,這張 banner 我看到的第一眼就很喜歡,有很符合個人狀況所以我放了很久,從 2007 年五月開始就一直放著,也有連結回去,直到前陣子整理網站的時候才發現,當初連回的串連網站已經死掉了!然後我就花了些時間尋找替代方案。

blog.othree.net 2006-08-13

考古研究了一下,時間のないサイト運営者リング的網址也變動過不少次,後來可能是為了一勞永逸,所以轉移到 Google Site,當時網址是:

https://sites.google.com/site/happybusy/

只是沒想到在 Google Site 2023 年二三月之間的一次版本整合之後,網站就不見了,然後根據 internet archive 上的資料,找到當初原作者是一位筆名叫「すか」的繪師兼漫畫家,不過商業連載不多,同人社團叫「しろくま屋」(白熊屋),在 melonbook 也還有賣東西,然後還發現以前還有賣周邊,然後在推特上也找到另外一個站,路徑不一樣:

https://sites.google.com/view/happy-busy/

雖然在すか的推上沒有承認也沒有否認,不過應該是原作弄的,最有參考性的是這串推文

時間のないサイト運営者リングサイトのドメイン
happy-busyは私が考えました(笑

-- すか@えりまき (@skysuka) September 19, 2023

大概就是他畫了新的圖,然後還挑了 happy-busy 這個名字,發文時間是 2023 年九月,當時新站也已經上線了一陣子了,只不過到今天新圖也沒擺上去就是。總之,雖然沒有很直接的承認,加上新站也沒也什麼詭異的跡象,我就還是把連結改過去了。

文章最後,還是想來感嘆一下日本真的很多閒人(稱讚的意味),各種古老冷門數位資料的收集整理非常多,連這些網站 banner 都有人整理,而且資料還留存到現在,像是這份「消滅した主張系同盟ウェブサイトリングの一覧」就列出了一堆已經消失了的個人主張系網站串連(Web ring)。

🔲 ⭐

Dialog 的魔法

HTML dialog

HTML 在 2014 的 HTML5 之後,其實就很少有什麼新的標籤,比較多是在各種細節的釐清和標準化各種未定義行為,不過在這些屈指可數的新標籤中,有一個比較廣為人知的,就是 <dialog>

<dialog> 的出現和前端工程實務上的發展很有關係,我個人認為它其實就是古早時候的 confirmalert 的現代版本,十多年前大部分的網路服務有類似需求還是直接用這兩個原生的互動介面為主,不過因為是原生的,對開發者來說可控性很低,加上以前的版本很容易會把瀏覽器卡死,使用體驗也不太好,現在的版本則考慮到使用者隱私也多了很多限制,加上樣式無法客製,所以在前端工程開始熱烈發展之時,很多網站也都開始自己做自己的對話框了;其中,最具代表性的或許是當年紅極一時的 Bootstrap 的 modal 了吧。

Bootstrap Modal

這些各家自製的對話框都很不錯,設計漂亮、功能完善,不過它畢竟沒有魔法(那些無法透過網路標準辦到的東西),有幾個問題還是無法克服,首先第一個就是,它無法永遠保持在最上層;第二個就是,使用者還是有可能意外 focus 跑到 modal 對話框之外的元素上;最後一個是,<dialog> 是如何沒有外層元素,卻可以垂直水平置中且本身大小是非固定的?其實我一開始就是對最後這個問題感到疑惑,才開始認真的研究 <dialog>,結果一研究下去,發現超多的細節的。

在回答問題之前,先來介紹一下 <dialog> 吧,首先 <dialog> 預設樣式是 display: none; 隱藏起來的,不考慮直接改 CSS 的話,要讓它出現有幾種方法,首先是透過 open 這個專屬的新 attribute:

<dialog open>
   This is a dialog
</dialog>

這樣就會讓 <dialog> 出現在畫面上,表現就如同一般的 <div> 標籤,第二種方法則是透過 JavaScrpt:

dialogNode.show()

這樣的效果和 open 一樣,然後除了這兩個方法之外,還有一個最特別的:

dialogeNode.showModal()

showModal 會讓這個 <dialog> 出現在網頁的最上層,並且保持置中,而且同時,網頁上除了該 <dialog> 以外的地方都會無法互動。

在這邊,一下子三件以前辦不到的事情都出現了:

  • 保證在網頁的最上層
  • 只有一層標籤就水平垂直置中
  • 其他地方都無法互動

那麼,這些事情是如何辦到的呢?首先就來說說第一點吧,如何能夠保證 <dialog> 一定在最上層呢?那就是一個新規範的東西了,叫做 top Layer,標準則是放在 CSS Positioned Layout Module Level 4,這東西指的現在瀏覽器在繪製文件之餘,還要建立一個獨立於文件之外的 stacking context,然後該 context 一定是在其他所有 stacking context 之上,尺寸則是和 viewport 一樣大,這個 stacking context 就是 top layer 了,開發者是無法直接控制該 context,需要透過一些特定 API 操作,才能把東西丟到 top layer 來繪製,目前有用到 top layer 的除了 <dialog> 之外,文件上是還有寫到 fullscreen API 和還在初期的 popover,開發工具都已經有支援,下圖的開發工具的截圖中,文件的尾端就多了一個 top layer。

Top layer

根據前一點,可以知道其實 <dialog> 一樣是普通 DOM 節點,只是在用 showModal() 時會放在不同的 stacking context,一樣可以用 CSS 設定樣式,那麼,<dialog> 是如何只有一層標籤就置中的呢?這當中可沒有魔法,其實很簡單,也是一個很古早的水平垂直置中的方法之一:

dialog {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  margin: auto;
}

其實就是絕對定位 + 上下左右都設為 0 + margin 設定為 auto 的方法,等等,如果垂直水平置中這麼簡單,那大家怎麼會痛苦了幾十年還一直在尋求一個物件置中的方法?其實原因就在於,這個方法有個先決條件,就是該標籤的寬高必須是要明確定義的值,而不能是 auto,詳細的計算方式規範目前在 CSS Position Level 3 裡面的第五章「Old Absolute Positioning Layout Model」,更早則是 CSS 2 就已經有了,這一個章節是在介紹如果是絕對定位的標籤,要怎樣計算它的位置、寬高和 margin,有個表格詳細的列出各種情境的排列組合(是否為 auto):

Summary of rules for dir=ltr in horizontal writing modes

以 modal dialog 的例子來看怎樣計算水平的定位吧:首先來看屬性的組合,left 和 right 都是有值,值為 0、margin-left 和 margin-right 都是 auto,如果寬度是有值的話,那就是表格第二行中的第三項,算法就是:

margins split positive free space

剩餘的空間平分給兩個 margin auto,結果就會是水平置中;如果 width 是 auto 的話就是最下面一行:

auto margins → zero
solve for auto

意思就是 margin 的 auto 都為 0,剩下的空間都給設為 auto 的 width。這表格也解釋了為何有些 marign: auto 會有元件置中的效果,其實這個問題也在我腦中好久了,沒想到計算方法在 CSS 2 就已經有明確的定義好了。

回來看 <dialog>,它在 modal 模式下,是會水平垂直置中的,但是它的寬高表現也很像是用 auto 一般,是根據內容變化的,那到底是怎樣達成這樣的效果的呢?其實關鍵就是它的寬高是一個新的值:fit-content,完整的樣式應該是:

dialog {
  position: fixed;
  inset: 0; /* shorthand of top, right, bottom, left */
  margin: auto;
  width: fit-content;
  height: fit-content;
}

結果就是,因為 width 不是 auto,所以套用的規則就是表格中的第二行中的第三項,根據標籤內容決定標籤的寬度之後,剩下的空間就平分給 margin,達成置中的效果。

了解原理之後,就可以知道哪些 CSS style 宣告是和定位有關的,除了可以避免不小心覆蓋掉(我最最一開始就是因為自訂 CSS 讓它定位不正常才開始研究的),還可以隨心所欲的調整標籤的位置,舉例來說,我的版面有一個 sidebar 佔去左邊的 300px,然後我希望 <dialog> 是在剩下的主要區域內置中,那我就把 left 設為 300px 就好了。

終於來到第三個問題,是怎樣讓其他地方都無法互動的呢?這就也是一個 <dialog> 的特異功能,它有一個隱藏的 is modal flag,呼叫 showModal 時,除了會把該 flag 設為 true 之外,還可以讓文件中其它部分變為和有 inert 時一樣,什麼是 inert 呢?中文翻譯為惰性,可以讓互動元件失去活性,使用時機就是如果互動元件因為一些原因需要暫時性的停用,例如收合起來的目錄,這時候我們不希望使用者的 focus 移動到目錄內,甚至不小心點擊到,那就可以用 inert 這個屬性讓它失去活性,使用者的游標就永遠不會跑進去,也不會有互動事件。

然後研究到這邊,我突然想起另外一個在腦中疑惑許久的問題,modal 這個單字到底是哪裡來的?為什麼 Bootstrap 也是選這個字?然後為什麼 HTML 不就 dialog 這個字用到底呢?進一步搜尋之後才發現,原來這邊的 modal 不是指 UI 元件,而是一種流程,這個 modal 其實是 modal window(dialog) 的 modal,而這個 modal 是專指應用程式中一種特定的模式(modal 的字源即為 mode),在該模式之下,除了 modal window 之外的元件都被停用,使用者必須要先完成 modal window 內的互動才可以繼續。這就很像是古早時候的 confirmalert 一樣,不把它關掉就無法繼續用網頁,然後我也才理解為什麼會標準文件內還會提到 autofocus 流程、還有為什麼會有 returnValue 這個屬性可以用。

其實 Chrome 早在 2014 年就支援 <dialog> 了,然後還提供了個 polyfill(當然無法解決 top layer 的問題),不過 FirefoxSafari 則是要到 2022 才支援,我去找出 Firefox 的 issue 來看,一路看下來,Firefox 是約 2016 開始,斷斷續續的實作,在實做的這段期間,其實標準也一直有修改,Safari 和 Firefox 都是 2022 才正式支援,到 2022 正式支援時的版本已經蠻穩定了,所以可以說是直到 2022,<dialog> 才是真正意義上的可用,我則是直到今年才有考慮拿來用,然後也才生出了這篇文章,其實 <dialog> 還有很多細節,像是 ::backdrop:modalformmethod="dialog"returnValue、怎麼用 cancel 事件ESC 等,雖然內文礙於篇幅沒有介紹,不過我有用 codesandbox 做了個簡單的範例,有興趣的可以去玩看看。

最後,如果和我一樣是寫 React 要用 modal 模式的 <dialog> 的話,就一定要用到 useEffect,不能只操作 open 屬性,實作其實很簡單,我隨意搜尋一下也有看到一個 use-html-dialog ,也可以直接參考它的原始碼,關鍵的部分:

useEffect(() => {
  if (openModal) {
    ref.current?.showModal();
  } else {
    ref.current?.close();
  }
}, [openModal]);

其他參考資料:

🔲 ☆

やまに(yamani)旅館

やまに旅館 お手頃ふぐ梅

去年的名古屋之行因為所以然後就跑去了南知多,研究行程時發現當地冬天有虎河豚,也很多餐廳有套餐可以享用,加上在台灣要吃河豚相對比較不容易,所以在安排行程時就花了不少時間研究要找哪一間,做這種套餐的其實很多是旅館,蠻大部分是當地的小型旅館,沒有上國際的訂房網站,甚至有的只有電話可以聯絡訂房訂位的,後來我的搜尋方法就是用 Google Map 慢慢找,在上面找了很久,最後選的旅館叫 やまに(yamani)旅館,本來是打算住一晚,後來因為參加源氏香活動的關係,就改成只有去吃河豚套餐。

選擇 Yamani 旅館的一個主要原因是,雖然舊,但是看起來蠻乾淨,我也一直很想體驗看看比較在地的住宿體驗(雖然沒住),另外就是它們其實也是有上樂天旅遊可以接外國遊客,不過樂天旅遊訂的話會比較貴,所以就還是在官網訂(不過沒住宿的我忘了樂天能不能能訂),唯一比較擔心的大概就是我沒日本電話號碼吧,不過結果還蠻順利的,不多說廢話,就趕快來看看 やまに旅館 的虎河豚套餐吧。

我們訂的是梅套餐,菜色當然是比松或竹少一些,但是份量還是很多,首先是小菜:

やまに旅館 お手頃ふぐ梅

重點的河豚生魚片,非常大盤,這樣的份量台灣不知道會多貴:

やまに旅館 お手頃ふぐ梅

やまに旅館 お手頃ふぐ梅

やまに旅館 お手頃ふぐ梅

河豚生魚片很好吃,脆脆的口感非常特別,是整個套餐我最喜歡的,而且份量多讓我吃得很滿足。

やまに旅館 お手頃ふぐ梅

然後是另外一個主要餐點之一的火鍋:

やまに旅館 お手頃ふぐ梅

やまに旅館 お手頃ふぐ梅

河豚生魚片也可以用火鍋煮,不過就沒那麼好吃了,火鍋本身就味道很清淡,河豚肉就稍微比較硬,然後有一堆蔬菜,是整趟行程吃到最多菜的一餐了,給的菜和河豚肉還有豆腐等等差不多可以煮兩鍋。

然後是炸河豚:

やまに旅館 お手頃ふぐ梅

我們還有點兒童餐,也是很豐盛,這次名古屋行點了好幾次兒童餐,都蠻讓人滿意的,這邊的還有生魚片:

やまに旅館 兒童餐

やまに旅館 お手頃ふぐ梅

最後的雜炊,因為火鍋吃完時已經很飽了,但是又很想吃吃看所以請他做一人份,結果份量根本還是兩人吃也很夠:

やまに旅館 お手頃ふぐ梅 やまに旅館 お手頃ふぐ梅

甜點:

やまに旅館 お手頃ふぐ梅

套餐內容其實還有兩個附近的富古神社(音同河豚)的繪馬,可以寫下願望後他幫我們去綁,我們一個寫願望一個帶回家當紀念。

然後稍微放些旅館本身的照片:

やまに旅館 やまに旅館

洗手間超有年代感,但是很乾淨完全沒異味:

やまに旅館

兒童拖鞋是小熊維尼的皮拖鞋:

やまに旅館

玄關的擺飾:

やまに旅館 やまに旅館 やまに旅館

簽名板們:

やまに旅館

外觀:

やまに旅館

大門:

やまに旅館

結帳可以刷卡還有很正式的收據,然後因為非旺季又是平日,所以當天只有我們一組客人,女將(?)也很樂情的跟我稍微攀談,問我們怎麼找到他們旅館的,後來還送了小朋友一些東西,非常不好意思。

PS. 南知多很多旅館都有內部的全景可以看,似乎是當地的觀光協會之類的統一委託建制的,在 Google Maps 上就可以看到

🔲 ⭐

UI Event Order

我一直以來都對於 DOM 事件的順序抱有一種不確定的感覺,舉例來說,當使用者點滑鼠時,你可以預期到會有 mousedownmouseupclick 事件,但是它們的順序是什麼呢?可以確定的是 down 一定是第一個,up 一定在 down 之後,那 click 是在中間還是最後呢?更進一步,點在可以有 focus 的元件上,那 focus 事件的順序呢?如果已經有其他元件有 focus,那它的 blur 事件又是在 focus 的前面還後面呢?除了滑鼠事件外,鍵盤事件又更複雜,除了 keydownkeyup 之外還有 inputchange 和 IME 的 composition 事件等,總之最近實在是太在意了,就認真的弄了個測試網頁自己測試,之後又查找了相關的標準規範,這篇就來記錄一下這些事件的順序。

首先就來說滑鼠(指標裝置)相關的事件順序吧,第一個是滑鼠點擊,就是 mousedownmouseupclick,是在 mouseup 後才接著有 click 事件,其實仔細想了一下也是蠻合理的,要有 up 事件才代表完成了 click 事件。然後這順序其實是有定義在 UI Events 5.3.3 之中的,其中的最後一個表格就是一個標準的點擊時事件的順序,而且這個表格還包括了 mousemovedblclick 事件,這個章節中的其他部分則是滑鼠移動經過不同、多層的 DOM node 時,不同 node 上的 mouseovermouseout 事件的順序。

除了 Mouse Events 之外,其實現在瀏覽器的實作應該是都實作 Pointer Events 了,Pointer Events 涵蓋了各種指標式的控制方式,包括了滑鼠、觸控、觸控筆等,所以可以說 Mouse Events 只能算是子集,相對應的事件名稱基本上就是把 mouse 換成 pointer,例如:pointerdownpointerup,現在主流的瀏覽器也都已經有支援 Pointer Events 了,然後這時候問題就來了,Pointer Event 和 Mouse Events 誰先誰後?根據測試的結果,是 Pointer 先然後才 Mouse,所以更完整的順序是:

pointerdown
mousedown
focus
focusin
pointerup
mouseup
click

至於這個順序是怎麼決定的呢?根據 Pointer Events 的 11 章「Compatibility mapping with mouse events」 所述,瀏覽器開發時可以考慮同時發佈古時候的 Mouse Events,其中 11.2、11.3 就有提到先發佈 Pointer Events 接著再發佈對應的 Mouse Event。

然後還有一個細節是,根據 Pointer Event 4.2.3 The pointerdown event,如果在 pointerdown 事件裡面呼叫 event.preventDefault() 取消事件的話,後面的 mousedownmouseup 就都不會觸發。

我上面的那段事件順序,其實還多列了一個 focusin,這其實是一系列的新(相較於 DOM2)事件,包括了:

  • focusin 對應 focus
  • focusout 對應 blur
  • mouseenter 對應 mouseover
  • mouseleave 對應 mouseout

其實 mouseenter / mouseleave 是 IE5.5 時微軟先提出的,ppk 也有文章介紹過它解決了什麼問題,jQuery 當年也有支援,後來進入了 W3C 標準,現在是放到 UI Events 裡面,這些事件最大的差異就是它們不會 bubble 到外層,減少了很多問題;focusin / focusout 則是剛好相反,它們會 bubble 而 focus / blur 不會,一樣 ppk 也有文章介紹到,簡單說就是 focus / blur 不會 bubble 只有 capture(外往內到 event target 的過程),但是 IE 不是用 addEventListener 所以沒有 capture 階段,所以會無法實作出 event delegation,然後只能用當年微軟 IE 特有的 focusin / focusout 事件,現在也是標準化,收到 DOM 3 Events 裡面;而除了這四組之外,其實 Pointer Events 也有 enter 和 leave,一樣順序是在 over 和 out 的後面,然後這些成對的事件,都是比較早定義的那些先發生,才接後來定義的,和有沒有 bubble 無關。

接著來說 Keyboard Events,這邊就針對 input 節點上的,一個鍵盤按鍵按壓的動作,會產生 keydownkeypresskeyup 三個基本的事件,通常按鍵盤按鍵就是為了輸入東西,所以會有個也是比較新的 input 事件,會在 keypress 之後,input 則還有一個成對的 beforeinput,如果在 beforeinput 內叫 preventDefault() 的話則可以阻止文字的輸入,總之順序如下:

keydown
keypress
beforeinput
input
keyup

change 事件則是要在 blur 時才會有,順序是先 changeblur

change
blur
focusout

這個順序是定義在 HTML 的 User Interaction 一章的 6.6.4 Processing model 裡面,明確的寫下要先 commit change 後才 blur

如果有用 IME 的話,事情就很不單純了,還會有 Composition Events,順序是在 beforeinput 前面,剛開始組字會同時有 compositionstartcompositionupdate 兩個事件,然後沒有 keypress,之後的輸入組字則就是只有 update

keydown
compositionstart
compositionupdate
beforeinput
input
keyup

Composition Events 現在標準的文件是放在 UI Events 裡面,不過文件中範例的順序和實際測試的結果並不一致,目前的文件草稿中 compositionupdate 是在 beforeinput 之後,不過其實現在瀏覽器的順序是在 UI Events 的 Issue 354 提出的變動,只是目前文件還沒有發布更新的內容。

結束組字的時候,不同瀏覽器的行為就有差異了,首先是按下 Enter 完成組字時,Firefox 的話不會有多一個 update,直接就是 compositionend,然後是在 beforeinputinput 之間:

keydown
beforeinput
compositionend
input
keyup

Chrome(v123) 的話就會有多一個 compositionupdate 然後 compositionend 順序也不一樣,會在 input 的後面:

keydown
compositionupdate
beforeinput
input
compositionend
keyup

其實 UI Events 文件 5.7.5 內的範例是 Firefox 那種沒有多 compositionupdate 的順序,這個 5.7 章節內其實還有不少其他情境下的事件順序,像是手寫輸入,取消輸入等等。

如果是還沒完成組字,直接切換輸入法強迫結束組字,事件順序都和按下 Enter 都一樣,如果是組字到一半直接切換視窗,就是標準沒定義到的狀況了,Firefox 的行為比較接近上面的樣子,先完成 inputblur

beforeinput
compositionend
input
blur
focusout

Chrome 則是會先產生 blur 然後接 compositionend

change
blur
focusout
compositionend

以上,大概紀錄了我一直以來都有疑惑的使用者行為所產生的事件們的順序,最後附上我用的程式碼(超單純):

const events = [
  "keydown",
  "keypress",
  "keyup",
  "change",
  "compositionstart",
  "compositionupdate",
  "compositionend",
  "beforeinput",
  "input",
  "click",
  "auxclick",
  "contextmenu",
  "mousedown",
  "mouseup",
  "focus",
  "focusin",
  "focusout",
  "blur",
  "pointerdown",
  "pointerup",
  "paste",
];

const elem1 = document.getElementById("target-1");
const elem2 = document.getElementById("target-2");

events.forEach((event) => {
  elem1.addEventListener(
    `${event}`,
    () => {
      console.log(event.target.id, event);
    },
    false
  );
  elem2.addEventListener(
    `${event}`,
    () => {
      console.log(event.target.id, event);
    },
    false
  );
});
🔲 ⭐

2023 名古屋

高山陣屋

去年十一月底的時候,安排了一趟名古屋的旅遊,一開始的目標很簡單,就是帶小孩去樂高樂園,所以挑選了名古屋,結果這趟旅遊在出發前還真是一波三折,首先是因為差不多快要楓葉季了,所以挑選時間時就想說挑個可以順便看楓葉的時間,又考量到公司專案的時程,兩週不錯的時間挑了第二週,和本來那個專案的時間差了兩三週,結果公司專案最後還是拖到我出國前還沒上線;接著在規劃行程時,本來想說一天去下呂溫泉,然後前面四天後面五天都在市區或是近郊,接著看回程要怎樣到機場時,考慮到有想多買行李箱,所以可能無法搭電車,就看了一下計程車費,不意外的很貴,想了一下去查了一下租車一天的價錢,結果發現差不多!但是都租車了,乾脆多租幾天在附近玩,所以就看起了中部國際機場所在的知多半島的觀光景點,發現有虎河豚套餐可以吃,後來老婆覺得可以不用太多小孩行程,想去飛驒高山,排到最後變成:

11/25 名古屋車站
11/26 Toyota 博物館、大須商店街
11/27 栄、Harbs 本店、東山植物園
11/28 Lego Land
11/29 三井 Outlet、名花之里
11/30 飛驒高山
12/01 下呂溫泉
12/02 犬山城、住南知多(源氏香)
12/03 知多半島、河豚套餐
12/04 臨空區、機場回程

結果行程排定後,快要到出國前,又傳出高山那邊下大雪,高速公路限制沒雪胎不能上去,害我又趕快處理租車的問題,還好 Toyota 租車有一個外國人專用的號碼,可以講英文,雖然是社恐一名還是只能硬著頭皮打國際電話去加雪胎,多了一萬多日圓。至於出發前一週家裡洗衣機壞掉又是另外一回事了...

到這邊想岔題說一下,前陣子有很多文章在講日本有一些服務會某些程度給外國人加價,其實 Toyota 租車也是有點這種情況,在日文版網頁很多折扣在其他語言是看不到的,不過我是認為這比較不是不願意給外國人折扣,或許只是單純因為不同系統沒有開發資源,加上剛好可以減少複雜度,避免節外生枝,降低溝通成本,當然我是日文網站註冊在日文網站預約的,當初價錢還不錯,不過為了雪胎折扣掉的錢又都回來就是XD。

回到車子的部分,這次租的是新款的 Hybrid 動力的 Sienta 七人版,後面行李空間可以放兩個大行李箱加上推車和登機箱還有些空間,駕駛座位附近也很多空間,可以放各種東西(鑰匙、飲料、小包包等),不過鈑金什麼的感覺就比較單薄了。

Toyota Sienta

Toyota Sienta

接著來介紹一下實際的行程吧:

首先第一天到中部國際機場,搭電車到名古屋站,住在萬保龍酒店,走路就可以到,所以規劃就是車站附近商圈逛逛和吃晚餐,本來有想第一天就去吃鰻魚飯,結果班機延誤一小時,去到白河看已經一大堆人,後來就是高島屋餐廳街隨便找,然後隨便逛了一下高島屋就回旅館了。

說到班機延誤,這次搭的是國泰的 CX530,直飛,其實我本來想說香港的航空公司怎麼會可以從台北直飛去日本,結果因為班機延誤一查才發現,原來其實這台是早上從香港到台灣,然後又馬不停蹄飛去日本,沒狀況的話會是同一台飛機下午又飛回台北(CX531),然後再回到香港,表定時間是早上九點出發然後回到香港是晚上十點了,非常忙碌的一台飛機。

回到名古屋車站,這邊有兩個要來推薦一下,首先是萬保龍酒店 Raffine(Montblanc Hotel Raffine Nagoya Ekimae):位置不錯價錢實惠,而且還蠻新的,除了這些之外,裡面用的設備都蠻不錯的,列舉一下:

Montblanc Hotel Raffine Nagoya Ekimae

另一個要推薦的就是名古屋車站的高島屋了,就在 JR Gate Tower 那一群裡面,非常的好逛,而且我這幾天也根本都沒逛完,裡面有 Uniqlo(可退稅)、GU、Bic Camera、Village Vanguard、三省堂書店(超大),三省堂有很多專業冷門書:

三省堂書店 名古屋本店

鐵道專區的一小櫃:

三省堂書店 名古屋本店

超大野貓玩偶,剛好在辦特展:

三省堂書店 名古屋本店

一樓還有迪士尼專賣店和 Ghibli 專賣店,飛行石抱枕很好笑:

名古屋

然後隔壁棟還有手創館,這次幾乎沒去逛到就是,地下室食品區也是很大,我們每次去日本都會順便買一些日本的高湯包(だし),主要是買兵四郎和茅乃舍的,這兩家的高湯包也都不是隨便可以買到的,不過這邊就是都有,兵四郎在超市區,茅乃舍則是有專櫃在同一層附近而已,袋子很豪華:

名古屋

第二天和第三天是週六週日,其實這兩天沒有一定要哪天去哪裡,唯一有限制的就是東山植物園楓葉季的夜間點燈只有五六日,不過總之這第二天我們先去了栄的 Harbs 本店,在那邊隨便逛,在 Oasis 21 逛到一間哈利波特專賣店,然後大國藥妝店買了藥妝後回去名古屋車站附近的白河吃鰻魚飯。

栄

Harbs 本店的限定款蛋糕:

HARBS 本店

白河的鰻魚飯、魚骨仙貝:

うなぎ和食しら河 名駅店

うなぎ和食しら河 名駅店

第三天就比較精實了,一早先在車站附近地下街的 Komeda 咖啡吃早餐,然後去了 Toyota 產業技術紀念館,結果剛好遇到第 700 萬位入場的訪客的頒獎,覺得有點可惜的是,其實我們早餐等了有點久,然後吃完搭車到荣生站時就發現那邊也一間 Komeda 咖啡...,如果當初有研究完整一點,就不用在車站那邊浪費時間,搞不好有機會成為第 700 萬位入場的XD。

トヨタ産業技術記念館

Toyota 產業技術紀念館展出的東西很多,分兩大塊,紡織和汽車,紡織的部分則是從古早時候的紡織技術開始介紹到現在的大型自動化的設備,而且很多機器都可以讓它動給你看,後半汽車則是從材料加工開始介紹,甚至還有現場實際展示金屬加工,汽車部分也是很多東西都會動給你看,還有可以隨便你玩的方向盤等等。

トヨタ産業技術記念館

午餐就吃館內的餐廳:BrickAge,餐點和價位比起來算是蠻不錯的,擺盤是比較精緻的路線,但是價位還是差不多一般博物館內附設餐廳的價位。

BrickAge

下午去了大須觀音和商店街一下,這條商店街我就覺得還好,大須觀音那邊看到有些自願者 cosplay 後在幫忙整理環境,蠻特別的。

大須観音

大須観音

傍晚就開始移動到東山植物園了,目標就是本次名古屋行程的重要目標之一的楓葉了,不過到達時已經完全天黑了,所以只有看到夜楓。

東山植物園 夜楓

東山植物園 夜楓

東山植物園 夜楓

東山植物園 夜楓

第四天就是主要目標之二的樂高樂園,相較於迪士尼,樂高樂園小很多,而且土地形狀也比較不漂亮,不過對於小小孩來說是蠻適合的。

LEGOLAND Japan

LEGOLAND Japan

樂高樂園也只有營業到傍晚,不像迪士尼還有到晚上,我們也本來就打算晚餐要回車站附近吃。

第五天白天去了三井爵士之夢 outlet,傍晚則是計畫去名花之里看燈飾,出發之前其實也是研究許久,最後決定是全部搭巴士,沒有買套票,運氣還不錯等車都沒等太久(其實早上出發時是用跑的才趕上),位子也剛好夠,最後回名古屋車站那班差點客滿就是。

名花之里的燈飾規模真的很大,而也很認真弄,不會有稀稀落落的:

なばなの里

なばなの里

今年的主燈則是金字塔:

なばなの里

第六天早上一樣是在名古屋車站附近商圈逛逛,午餐後去租車出發往飛驒高山,中間路上有遇到小雪,然後到高山時天也已經都黑了,路上幾乎也沒什麼人,不過那個有名的燒肉店還是排很多人在等,後來找了一家好味燒的餐廳「獨樂」,然後去逛超市結束這天的行程。

ひるがの高原SA

お好み焼き独楽

飛驒高山

第七天白天在飛驒高山觀光,去了高山陣屋、宮川朝市、高山物產館、飛驒之里,結果早上也是沒仔細研究,順序錯了,本來應該要先去宮川朝市然後才往陣屋方向,順便要去看那條三町的老屋街區,結果一開始就跑錯方向,錯過那條老街,然後高山也都沒下雪,其實心理還是有點想看看雪景的。飛驒之里是一些老屋的集落,其實是搬遷過來的,有些是因為蓋水壩所以遷村之類的原因,也是第一次有機會進到合掌屋理參觀,很意外的是,裡面空間其實超大的。

飛驒高山

高山陣屋

飛騨の里

之後就開車往下呂溫泉,這邊有一個失算的,就是這段都不是高速公路,結果害我高速公路 pass 虧到,不過這段路程還算蠻漂亮的,晚上則是入住下呂的冨岳,算是傳統形式的溫泉旅館,早餐晚餐都在房間吃,有大浴場也有包場的時段可以挑。

下呂温泉 冨岳

下呂温泉 冨岳

第八天早上去下呂溫泉街逛了一下,然後去溫泉寺,楓葉雖然已經開始掉了但還是很漂亮,之後就開車下山,這段路其實蠻漂亮的,途中經過一個叫下原水壩的地方,經過時就覺得很漂亮,對岸還有火車經過,結果後來發現那邊還真的是一個小有名氣的拍照點。午餐則是吃下山後剛好路過的感動的肉與米,事前有查到這間不過沒預期到會剛好經過。

温泉寺

感動の肉と米 鵜沼店

感動的肉與米是一個蠻特別的餐廳,可以說是最佳化過後的肉排加米飯的餐廳,東西蠻好吃的,我看網路上有人介紹過東京的店,不過東京店似乎小很多,店內的人來來去去比較不好拍照所以就沒什麼照片,我連自己的肉的照片都不見了。

之後前往犬山城,這趟行程沒去名古屋城反而選擇犬山城,主要是因為犬山城天守是國寶之一,不過天守之外保留下來的部分比姬路城少很多,不過也因此省了很多時間就是,總之就是上去繞了一圈天守這樣,城內倒是沒什麼東西可以看。

犬山城

犬山城 天守閣

然後住宿就是前一篇文章介紹過的源氏香了。

第九天是回國前一天了,這天本來規劃就是知多半島為主,早上去知多半島最南端的羽豆岬,中午吃河豚,下午隨意逛逛,然後晚上去 J Hotel 臨空。

羽豆岬

やまに旅館 お手頃ふぐ梅

不過到中午行程結束後,發現沒買小倉山莊的仙貝,所以下午就決定往北走回頭路,跑了一趟小倉山莊的天白店,順便跑高速公路少虧一點 pass 的錢,其實照本來的規劃應該是要前一天從犬山城往南時過去的,這間店的位置其實意外的偏遠,我覺得應該是沒什麼海外觀光客會到這裡,開車過去途中還經過好一大片的工業區;然後小倉山莊,我真的是覺得很厲害,賣仙貝也可以把商品包裝成這樣,然後店內可以擺的讓人目不暇給,也真的是讓我覺得很佩服,當然東西也好吃。

小倉山荘 天白店

小倉山荘 天白店

小倉山荘 天白店

小倉山荘 天白店

雖然跑去小倉山荘有點走回頭路,不過也因為跑這一趟,還有機會順便逛了一下 V drug 和お宝創庫 鳴海店,在 V drug 也第一次在日本看到了 Costco 賣的那種 Attack Zero 超大補充包。

お宝創庫 鳴海店

お宝創庫 鳴海店

Attack Zero 補充包

之後就直奔旅館 J Hotel 臨空,旁邊的 AEON Mall 真的超級大,行李丟進房間後又跑去 Costco 逛,我有隨便拍了一些店內商品,可以從這張開始看,也順便在那邊吃了晚餐。

AEON Mall 常滑

J Hotel 臨空這次住起來感覺也很不錯,2023 剛重新裝潢過,有製冰機洗衣機,地理位置也很不錯,就在臨空站旁邊,離中部國際機場和常滑站都只有一站,旁邊 AEON Mall 走路就可以到,房間大小也都不錯,部分房間還有配 Aladdin 投影機,就是那個現在很流行的西瓜遊戲的開發廠商的那個投影機,本來有想請他們幫忙安排,不過入住的時候忘了,但是被安排到很高的樓層是也不錯,房間正對 AEON Mall,看起來也是蠻震撼的,如果要拍中部國際機場或是電車,其實公共區域走到邊邊有個小陽台可以到外面拍,視野很好,也可以看時刻表來拍電車,一大早光線很不錯。

中部國際機場

第十天也是最後一天,早上打算去常滑市的招財貓大道,在飯店吃早餐時發現有「想哭的我戴上了貓的面具 mini 原畫展」,才發現到常滑市就是該動畫的舞台,展覽也有列出聖地巡禮的點,不過沒什麼時間就沒細看了。飯後開車去常滑站附近逛了招財貓大道後,又接著逛了陶瓷器散步道去找巨大貓咪,必須要說陶瓷器散步道蠻不錯的,很悠閒又很多廢墟也很多商店,如果可以安排一整天在常滑的行程其實也蠻不錯的,可以早上來市區、中午找間餐廳、然後下午可以去 AEON Mall、Costco、明太子公園那一塊,光是 AEON Mall 就可以逛超久,旁邊還有個小賽車場,不想逛街也可以去玩玩,或是下午去機場的 FLIGHT OF DREAMS 參觀,然後再來 AEON Mall 也很不錯。

想哭的我戴上了貓的面具 mini 原畫展

とこなめ招き猫通り

やきもの散歩道

とこなめ見守り猫「とこにゃん」

之後因為還有時間就去明太子樂園,然後 AEON Mall 吃午餐、隨便逛逛然後就去機場了,機場去領貨和買了一箱蝦餅,蝦餅本來在那邊挑半天,回來後覺得應該全部買綜合就好(PS. 真的蠻好吃)。

順帶一提,這間 AEON Mall 也有 Village Vanguard,而且有一半是 Village Vanguard Outlet,是我第一次看到這間書店的 outlet。我第一次知道 Village Vanguard 其實是被表哥帶去的,當時他們在高雄有開分店,中文店名叫「比利治玩家」,就是專門賣一些怪東西 ecxiting book store,到底賣什麼可以參考我從這張開始的照片,或是上他們官網逛逛就知道了。

かねふく めんたいパークとこなめ

AEON Mall 常滑

Village Vanguard 常滑 AEON Mall

最後,就來說說這次旅行的收穫與缺憾吧,首先是收穫的部分,第一個就是稍微體會到下雪天駕駛的感覺,不過因為雪不大,也只有在高速公路上,所以沒有到雪地駕駛的程度;第二個是河豚大餐,之後想單獨寫一篇文章介紹;然後第三個就是常滑和臨空區意外的還不錯,本來也有想單獨寫一篇文章,不過上面已經介紹的差不多了。

至於比較缺憾的部分:

  • 沒有看到高山雪景,不過我也有點害怕真的要雪地駕駛就是;
  • 少去了羽豆岬旁邊的師崎漁港朝市;
  • 東西買太少;
  • 沒時間去鈴鹿賽車場;

其實我當初規劃在市區近郊的行程有好幾個,可是因為後來市區天數縮水就沒機會了,這邊來列一下:

  • 鈴鹿賽車場,應該可以整個白天,不過要小心有比賽的日子,特別有興趣是因為有可以上真的賽道開電動車的體驗,不過當然不是房車大小那種,但是也有雙座位的車種可以讓小孩在旁邊;
  • 名古屋港:可以參觀南極探測船 5001 富士,因為之前看了比宇宙更遠的地方,所以其實還蠻有興趣的;然後可以搭水陸巴士;接著去名古屋港水族館,不過如果想看企鵝散步時間可能要研究一下怎樣搭配比較好;
  • 吉卜力公園,應該可以一個整天,不過這次因為小孩都還沒看過所以就沒安排,買票也還有點複雜,有想去的話可能要好好花時間研究;
  • 樂高樂園加磁浮博物館,看地圖距離好像還好不過其實步行走的話還蠻遠的,加上樂高樂園我們離開時也已經五點多,所以就沒機會去磁浮博物館了;
  • Toyota 博物館,除了我們去的產業技術紀念館之外,其實 Toyota 還有一間博物館,展示的東西內容也和產業技術紀念館不一樣,產業技術紀念館比較著重在各種技術的發展,而 Toyota 博物館就真的是以展示車輛為主的樣子。

最後就是其他的遊記了:

🔲 ☆

Sign-in with OOO ID

最近工作上在研究 Sign-in with Apple/Google ID,其實這件事情也作過很多次了,不過距離上次也有點久了,不知道那些 SDK 有沒有什麼改變,所以還是要重頭來,而且這次多研究了一個 Apple,有搞懂些以前沒釐清的細節,想說紀錄一下。

首先就是,我發現到 Google 和 Apple 現在都會回一個 ID Token,內容則是 JWT,而且是認真的 JWT,真的會有帶一點使用者資料(像是 email)的,可以用來作 user authentication(認證)用的,這在以前只有 OAuth 2.0 的時候是沒有的,查一陣子資料才發現這其實是 OpenID Connect(簡稱 OIDC) 規範的,該規範是是 2014 年發布的,其實還比 JWT 早定稿。

相較於 OAuth 2.0 做的是 authorization(授權),OIDC 做的則是 authentication(認證),只不過 OIDC 是整個依附在 OAuth 2.0 的架構上,利用的就是 OAuth 2.0 的 response_type,本來只有 codetoken 兩種,在 OIDC 多提供了 id_token,ID Token 是用 JWT,而且也有明確定義有裡面的 user profile 相關的欄位(不是定義哪些是必須提供,而是定義好語意和對應的欄位名稱)。

第二個則是我一直存疑已久的問題,就是 OAuth 2.0 的設計上基本是用 redirection flow,而且 redirect_uri 也是必要的,但是 Google 其實一直都支援純 JS 的方案,也就是說 Relying Party(應用程式端)不需要實作一個 redirection endpoint 來接資料,前端的 JS 就可以直接拿到 authorization code 和 access token,這次也認真的研究了這個問題,結果發現,Apple 的 OAuth 流程中,response_mode 給的值是目前不在標準內的 web_message,而 Google 則是 redirect_uri 給的是一個沒見過的 scheme:storagerelay:// 的 URI。

其實我一開始以為這些設計,是各個公司自己想一想然後就自己做下去的,結果沒想到其實不是,首先是 Apple 的實作,用的是 OAuth 2.0 Web Message Response Mode 這份草稿的設計,這份草稿其中一位作者 Nat Sakimura 現在是 OpenID 的 chairman,而且他也是其他很多相關規範的作者(像是 JWT),不過這份草稿只有一版且沒人更新,有很多細節沒有寫定,大部分都是提供範例程式碼而已,所以 Apple 有些東西不是照範例做,例如 message 的 payload;Google 實作的則是 OAuth 2.0 IDP-IFrame-based Implicit Flow,這份文件其實是我最後才找到的,因為這份只有出現在 OpenID 的 mailing-list,而且也完全沒有討論和更新,不像前一份還有發到 IETF,回到文件內容,這份的作者,就全部都是 Google 的人了,內容完整許多,也有定義好 message 的 payload 結構,不過還是有些細節有缺,像是認證完成後的回傳事件,現在 Google 用的事件名稱在這份文件中就找不到。

除了這兩份草稿外,其實還有一份是 Curity 提出的 OAuth 2.0 Assisted Token,一樣有發到 IETF,而且還比較有在更新,最新一版是 2021 的,Assisted Token 的設計是多給了一個流程叫做 Assisted Token Flow,用不一樣的 URL 來使用這個 flow,這個流程的最後一步就是 postMessage 回到 opener/parent,規範寫的比較完整,包括各種新屬性的 registry、message 的 payload,還有安全性相關的考量都有,不過我看一看有些地方覺得有些疑惑,第一個是 message payload 的結構似乎辨識度沒很高,第二個則是完全沒提到 refresh token 和 authorization code,不確定是目前還沒考慮到那邊,還是因為安全性考量把它們先排除。

第三個是 Apple 的實作,雖然基本上還是照著 OAuth,但是其實限制更多,首先就是,scope 就只有 email 和 name 可以拿,而且 Apple 做成,只有第一次 authorization 時,會把 user profile 傳給 RP,之後是拿不到的(不過 email 有在 id token 內),然後,雖然可以拿到 access token,但是其實完全沒有可以使用它的 API endpoint,所以什麼事情都不能作,真的只能用來做 authentication,最後一個,就是用 code 換 token 時,要給的 client_secret 參數還特別麻煩,要自己組一個 JWT(但是也因此會 expire 比較安全),然後用之前從 Apple Developer 後台生好的 secret key 去算 signature。

最後一個想紀錄的就是,這幾份標準和文件裡面幾乎都有一個章節是 Security Consideration,內容雖然不全面但是還蠻值得一看的,也有提到一些攻擊手法,而除此之外,其實還有一份文件:RFC6819: OAuth 2.0 Threat Model and Security Considerations,內容就是有說明 OAuth 2.0 各種設計在安全性上的考量(像是為什麼有 Refresh Token,什麼情境下它有助於安全性的提升),以及各種可能的攻擊手法。

🔲 ☆

Remove Disqus

EFF Privacy Badger

前陣子有整理了一下部落格的東西,大致上作的事情是:

  • 拿掉 Google Analytic
  • 拿掉所有的 SNS 按鈕
  • 拿掉 Disqus
  • 換 web font 服務

首先是拿掉 Google Analytic 這件事,其實我已經想很久了,一部分原因是不想餵資料資料給 Google,另一個原因則是剛好現在舊的 Universal Analytic 已經停用了,一定要改成用 GA4,所以趁這個機會就乾脆的拿掉了,不過還是會好奇哪些內容比較有人看,所以又花了點時間研究了 web log 分析軟體,因為不想多架服務,老牌的 AWStats 介面現在實在是無法接受,所以現在選的是 goaccess 當成 terminal 工具來用,不過它其實還蠻強的,選項很多,要當成服務跑也可以。另外就是如果還是偏好前端的追蹤, Twitter(現在的X) 上也有朋友推薦了 GoatCounterumami,分別是 golang 和 js 寫的服務,有開源也有線上的服務,有限度的服務使用額度,當然自架的話也可以,不意外的都需要資料庫,非開源專案的話也有一個 Plausible 看起來不錯。

第二個是 SNS 按鈕,其實以前有三個按鈕,分別是 Google+、Facebook 和 Twitter,然後我都是用 iframe 掛上按鈕的,這樣比較不用擔心直接掛第三方 js 的各種問題(隱私、安全),不過 Google+ 收掉了,FB 按鈕因為 Firefox container 的關係我其實也都看不到,後來忘了什麼原因也拿掉了,最後只剩下 Twitter 的,結果最近發現我掛按鈕使用的那個 Web Intent 也被改的無法在 iframe 內顯示按鈕了,所以就乾脆的剩下的全拿掉,最後只留下一個用 Web Share API 的按鈕。

然後是 Disqus,其實留言系統原理簡單不難,但是真的要做的話也是很麻煩,一來要有資料庫,這樣現在很多的靜態網頁產生工具就先死一票了、二來還要有能檔 spam 的能力,所以 Disqus 的出現真的是補了一個很大的缺口,我以前是很喜歡 Disqus 的,畢竟它是這種需求數一數二的先行者,該公司的工程師也很認真的研究 3rd party script 的技巧,我現在工作也有一部分是在寫 3rd party script,對此有興趣之餘,也對於這東西的麻煩之處很有感,不過現實就是開公司就是還是要賺錢,所以慢慢的它也是走向我比較不喜歡的方向,開始大量收集資料,然後甚至有人說開始有插入廣告了,不過除此之外,更大的一個原因是在我這邊的使用率實在太低,如果都沒人用的話,一直掛著也只是訪客被收集資料而已,於是我決定把整個迴響區塊都拔掉,帶來的副作用當然就是以前一些少數的留言也都消失了。

我在拿掉迴響後沒兩天,就剛好看到 HackMD 也拿掉 Disqus 的消息,跟著原推文下去找其實也有不少的替代方案,像是 cusdis、用 GitHub 的 giscusutterances 等,其實 Wappalyzer 上也有些替代方案(然後也可以看到 Disqus 佔有率目前還很高)。

其實還有另外一種類型的替代方案,就是去支援新的 protocol,像是 ActivityPubWebmention ,第一次看到 ActivityPub 加上靜態網站產生器的方案時,我就想起以前消失在 spam 的洪流之中的 trackback 機制,不過靜態網站產生器和 ActivityHub 相性不是那麼好,它其實也是和留言系統一樣,需要有 API endpoint 和資料庫,所以有辦法做到支援的選擇也沒很多,相關的服務和專案也相對不成熟,還需要不少手工;另外一個選擇 Webmention,則可以參考 Jason 的「透過 webmention 來搜集 blog 的社群迴響」,基本上是可以透過第三方服務來弄成純前端的方案。

最後一個就是 web font 了,其實本來沒有要調整這塊,只是上面幾項改完,發現網站幾乎要沒有追蹤器了,只剩下 Google Fonts 相關的 request,Google Fonts 一直是被歸類為潛在的追蹤器,實際上到底有沒有被偷偷用來當做追蹤器也無法證實,總之我就試著尋找替代方案,一開始想的是自己放檔案,因為我只有用到兩個英文字型,不過結果大小差了 10 倍,不進一步調整不行,就在這時候看到了 Laravel 因為 GDPR 的關係改用 Bunny Fonts 了,大概研究了一下,bunny.net 本身是 CDN 服務商,而 Bunny Fonts 就是主打無追蹤,所以 GDPR 沒問題,另一個特點就是介面和 Google Fonts 相容,也就是說只要把 domain name 換掉就好(我的狀況是還有 CSP 要修改)。

然後最後的結果就是如文章上面的圖片一樣,現在大部分頁面,EFF Privacy Badger 的檢查結果已經是沒有需要阻擋的東西了,只有部分文章有內嵌 Tweet 或 YouTube 影片的,就還是會顯示有潛在的追蹤器。

❌