PHPickerViewController
是系統內建的一個照片選取工具,透過 PHPickerConfiguration
設定它,然後從它的 delegate function func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
取得用戶選取的結果。看起來非常簡單直覺,直到我踩了坑...
]]>PHPickerViewController
是系統內建的一個照片選取工具,透過 PHPickerConfiguration
設定它,然後從它的 delegate function func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult])
取得用戶選取的結果。看起來非常簡單直覺,直到我踩了坑...
我的目標是要從回傳的 [PHPickerResult]
轉成 [PHAsset]
,首先要取得所有的 assetIdentifier
,接下來使用 PHAsset
的 fetchAssets(withLocalIdentifiers identifiers: [String], options: PHFetchOptions?) -> PHFetchResult<PHAsset>
得到 fetch results。
PHPickerResult
的 assetIdentifier
總是為 nil
?從 PHPickerViewControllerDelegate
我們可以得到 results: [PHPickerResult]
,然後就能將它轉成 assetIdentifier
array
let identifiers = results.compactMap { $0.assetIdentifier }
但我發現 identifiers
總是空的...
研究了好久之後才發現問題出在 PHPickerConfiguration
。
當我們要初始化它的時候,不能直接使用 let config = PHPickerConfiguration()
,如果沒有提供 photo library 參數給它,assetIdentifier
就會總是為 nil
。因此正確的做法如下:
let configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self
self.present(picker, animated: true, completion: nil)
PHFetchResult
跟 PHPickerResult
數量不一致?好不容易取得正確的 identifiers,接下來就是要透過 identifiers 取得 PHAsset
了。我們可以這麼做:
let fetchResult = PHAsset.fetchAssets(withLocalIdentifiers:identifiers, options:nil)
fetchResult.enumerateObjects() { asset, _, _ in
// Deal with the asset
}
但我發現 fetchResult.count
跟 identifiers.count
並非總是一致,可取得的 assets 可能會比 identifiers 少。明明我們確定 identifiers 都是正確且合法的,為什麼無法取得所有對應的 PHAsset 呢?
經過一番排查之後,我才發現這跟照片的存取權限有關:
如果使用者有限制 app 只能存取特定照片,即使
PHPickerViewController
可以讓使用者看到並選取任何照片,但實際可以取得的只有使用者允許的部分。
以上,就是我的踩坑之路。
]]>今年花了一些時間把我的第一台單眼相機 Canon 6D 出清,原因也很簡單,就是因為生活型態改變了,近年來幾乎都沒再使用過它。與其放在防潮箱,不如讓它到有需要的人手中繼續發光發熱。雖然現在都改用手機拍照了,但心中還是對單眼相機的成相品質與拍照感覺念念不忘,加上近年技術進步,隨身相機的體積放進 APSC 的感光元件已經逐漸普及,所以我就買了這台兩三年前的機型:Sony a6400。它體積輕巧、APSC 感光元件、外型好看、對焦迅速,已經完全可以滿足我日常出遊帶得出門拍得出來的需求;加上它是多年前的機型,價格便宜許多,CP 值很高啊。
原本我是使用原廠配鏡,後來發現它的光圈不敷使用,所以就入手這支評價很高的 Sigma 18-50mm f2.8 恆定光圈鏡頭。它體積小、重量輕、光圈大,對於不需要長焦段的我說,是支非常適合我的鏡頭。
原先只是看中它能無線移動的方便性,想要放在臥室追劇使用,後來卻是放在餐桌旁邊,方便吃東西的時候可以看個電視休息一下。另外,以前大人跟小孩會搶電視,現在就不會有這種情況了,大家可以各自看自己感興趣的內容。同時它也支援無線投影,我可以將筆電的內容投影到螢幕上,無論是作為第二螢幕或是想要分享螢幕內容都很方便。
XBOX Series S + XGPU
彌補了我從小到大都沒有遊戲主機的遺憾,也讓我看到現代的遊戲畫面有多麼精美。XGPU 更是美妙,隨時都有讓我感興趣的遊戲,也因為它是玩到飽的形式,讓我玩到一半就棄坑也不會有罪惡感,非常適合像我這種沒有太多時間玩遊戲的玩家!
對於像我這種長時間需要打字的人來說,擁有一把用起來愉快的鍵盤真的是一件超級重要的事情。雖然之前用了很多年的薄膜鍵盤,但我一直很清楚我喜歡的還是機械鍵盤,近幾年機械鍵盤的選擇越來越多,Mac 用戶最推崇的大概就是 Keychron 跟 NuPhy 這兩個品牌,最後我在 Keychron K3 跟 NuPhy Air75 之間選擇了後者,因為它的鍵盤配色實在是太有趣了~實際用起來的手感也是相當不錯,茶軸的力道回饋、75% 的尺寸,對 Mac 系統的良好支援,讓我用得很開心。至於多種 RGB 背光模式跟 VIA 自訂鍵位,倒不是我考量的點。
以上就是我今年的好棒棒清單,祝福大家也過個好年!
]]>安全:使用 end-to-end AES-256 加密、Salted Hashing 和 PBKDF2 SHA-256 算法來保護資料,並採用零知識架構,意味著只有你自己能解開資料,即使是 Bitwarden 的團隊也無法讀取你的資料。使用 Bitwarden,我們可以隨時建立高強度密碼並定期更換它們,減少帳號被盜用的風險。
方便:可以在任何設備上輕鬆存取你的帳號和密碼,並自動填寫登入表單。也可以使用它來生成隨機的高強度密碼,而且還可以自訂密碼規則。
開源:Bitwarden 是一個開源項目,它的原始碼是公開的,因此可以進行審查和稽核。這增加了它的透明度和可信度。
跨平台:支援多種設備和瀏覽器,例如 Windows、Mac、Linux、Android、iOS、Chrome、Firefox、Edge、Safari 等,甚至還有網頁版,讓你可以在任何設備上都能方便地使用它。
免費:它有提供免費方案,可以無限制地儲存和同步無限數量的帳號和密碼,並且在無限裝置上使用。如果需要更多功能,如 2FA、密碼健康報告等,只需要支付每年 10 美元的費用。
自託管:如果不希望將資料儲存於 Bitwarden 官方伺服器,可以經由簡單的步驟架設自己的 Bitwarden 服務平台。
共享:Bitwarden 不僅可以自己使用,還可以與其他人共享加密資訊。它提供了稱為「Bitwarden Send」的方案,讓你可以安全地與同事、部門或整個公司共享私人資料。
更多細節,可以參考付費方案的比較表。
用過密碼管理工具之後,我超後悔沒有早點使用它,它真的讓我再也不用費心管理與記憶密碼,可以放心使用超長與超複雜的密碼,提高帳號的安全性。
Bitwarden 具有高度的安全性、開源透明、跨平台、免費方案、自託管和共享等優點。如果正在尋找一個方便且安全的密碼管理工具,推薦你試試看!
]]>Arc 瀏覽器完整支援 Google Chrome 的 Extension,讓我們能夠擴充瀏覽器的功能,進一步提升上網體驗。許多常用的擴充功能都可以在 Arc 瀏覽器上使用,例如廣告封鎖、翻譯、密碼管理等等。此外,Arc 瀏覽器也提供所謂的 "Boost" 功能,讓懂 HTML/CSS/JavaScript 的開發者可以針對特定網站撰寫自訂功能。
Arc 瀏覽器的 Split View 功能可以讓我們在同一個畫面打開多個網頁,並可指定上下或左右並排,讓我們能夠更加輕鬆地做筆記或資料整理。例如,我們可以在一個區域內閱讀文獻或文章,同時在另一個區域中寫筆記或做總結。這樣做不僅提升了生產力,同時也提高了工作效率。我最常用這個功能來一邊開視訊會議一邊做會議記錄,或是一邊打開 ticket 一邊打開 PR 頁面。
Arc 瀏覽器的 PiP 功能是一個浮動的影音播放器,可以支援大多數影音網站,例如 YouTube、Spotify 等等。當我們觀看影片時,可以把影片放到 PiP 播放器中,然後切換到其他分頁繼續瀏覽其他內容。這樣做可以避免影片被其他網頁覆蓋。PiP 功能還支援拖曳和縮放等操作,讓使用者能夠更加輕鬆地操作。我很常一邊聽音樂一邊工作,這個功能對我來說超方便的。
當我們點到會開啟新分頁的連結時,Arc 會在當前分頁開啟一個置中小畫面,讓我們快速瀏覽連結內容。這對我來說非常的好用,尤其是在閱讀電子報、新聞網站、RSS Feed、社交網站的時候,讓我不用在不同分頁之間頻繁切換。如果快速看完之後覺得不錯,也可以把小畫面轉換成一般分頁,方便稍候繼續閱讀。
Arc 瀏覽器的 Little Arc 功能是一個簡化版的瀏覽器視窗,可以在其他應用程式點擊網路連結時自動開啟。這樣做可以提高瀏覽速度和效率,小小一個視窗不會覆蓋原先的應用程式,同時也可以減少開啟瀏覽器時的等待時間。
Space 與 Profile 功能顛覆我原先管理分頁的習慣,讓我們在工作上更加高效。舉例來說,如果我們同時需要管理個人和工作的網站,我們可以建立兩個 Profile,分別用不同的帳號登入,使我們可以快速切換帳號,避免混淆。同時,如果我們需要處理多個專案,可以建立不同的 Space,區分不同專案所需要的網站,讓我們可以快速切換,提高工作效率。此外,可以針對不同的目的,例如閱讀、工作、學習等等,建立不同的 Space,方便我們將網站整理成不同的分類,讓我們更加專注於目標。更棒的是它可以每個 Space 都指定不同的 Profile,Space 和 Profile 的功能結合,使得 Arc 瀏覽器成為一個很好的生產力工具。
在瀏覽網站的同時,想要瞭解某個分頁中是否有重要訊息時,你可以使用 Preview 功能。只需要將滑鼠懸停在該分頁的標籤上,就能顯示該分頁中的消息預覽。Preview 目前支援 Google Calendar、Gmail、Outlook、Outlook Calendar、GitHub、Linear、Notion、Figma、Cron 等多種網站,讓你能夠更加方便地一窺重要訊息像是未讀信件、下一個行程、被指派的 PR 等等。
Arc 已經成為我工作上不可或缺的工具了,如果你還沒有嘗試過 Arc 瀏覽器,不妨試試看。如果你想了解更多關於它的功能,可以來這個網頁看看。目前它還在封測階段,有興趣的人可以使用我的邀請碼。
]]>在以前要用 Auto Layout
來設置 UIScrollView
的 sub views 並不是一件讓人愉快的事情,雖然不複雜,但步驟就是有點麻煩。因為 scroll view 自身的特性,所以必須設定它本身的位置與尺寸,然後設定 sub views 的位置與尺寸,最後算出 contentSize
的尺寸。總結來說大概分成以下幾步:
UIScrollView
本身的位置與尺寸contentView
並加到 UIScrollView
的 sub viewcontentView
的位置,通常是四邊都貼齊 UIScrollView
contentView
,然後用 auto layout 設定這些 sub views 的位置與尺寸contentView
就可算出正確的尺寸,這就是 UIScrollView
的 contentSize
最讓人困惑且忽略的就是第三點,因為它很不自然,但在 UIScrollView
卻又是必須的。另外就是第四點,一定要有明確的位置跟尺寸,這樣才有辦法算出 contentSize
給 UIScrollView
使用。
從 iOS 11 開始,UIScrollView
多了 frameLayoutGuide
跟 contentLayoutGuide
這兩個方便的屬性,讓我們不必再用不自然的方式去設定 content 的 auto layout。
frameLayoutGuide
設定 UIScrollView
本身的位置與尺寸contentView
了,直接把內容加到 sub viewcontentLayoutGuide
建立 auto layout constraints整個設定流程變得自然許多,也更不容易出錯。現在我們只要確定 sub views 有設好明確的位置與尺寸,讓系統能夠算出 contentSize
即可。
每次換工作都是一次整理工作環境的機會,我的瀏覽器也藉此重裝,雖然每次的工作都不完全一樣,但我發現有些 extension 是不管在之前還是現在的工作、不管是公司還是家裏都會安裝的。以下就是我必備的幾個 extension:
]]>每次換工作都是一次整理工作環境的機會,我的瀏覽器也藉此重裝,雖然每次的工作都不完全一樣,但我發現有些 extension 是不管在之前還是現在的工作、不管是公司還是家裏都會安裝的。以下就是我必備的幾個 extension:
uBlock Origin
這一定是我第一個安裝的套件,實在是因為現在的網頁充斥著大量的廣告,不裝擋廣告套件根本無法好好瀏覽網頁了。
Bitwarden
我使用 Bitwarden 來儲存帳號密碼,透過這個套件就可以在瀏覽器快速存取密碼登入網站了。
Tab Group
很容易為了查資料不知不覺就開啟幾十個分頁,由於只是臨時查詢的頁面,存為書籤感覺不太必要,一直開著又很浪費資源。這時我就會用這個套件把分頁存成不同的 group 方便日後參考,不需要的時候就把整個 group 砍掉。Arc Browser、Vivaldi 跟 Sidekick 瀏覽器在分頁管理方面做得非常好,完全不需要這個套件。
TabCopy
這個套件可以讓你自訂格式,複製目前開啟的分頁資訊,對於時常需要寫信寫文件傳訊息的工程師來說很方便。
AutoPagerize
顧名思義就是自動載入下一頁的套件,幫忙我們節省寶貴的時間。
OpenAI Translator、Simple Translate、沙拉查詞
方便翻譯單字或片段的好工具。我最推薦使用 OpenAI Translator,翻譯的結果真的不是同一個等級的。
Cleary Reader、簡悅 - SimpRead 或是 Circle 閱讀模式
讓你瞬間進入沉浸式閱讀的 Chrome 擴展,提供與 Safari 類似的 read mode,以及其他更有彈性的設定。
Dark Reader
將網頁切換成暗黑模式,在夜晚或是低光源環境下閱讀,會舒服許多。
內容農場終結者
這個套件可以自動讓你在 Google 搜尋頁面直接隱藏農場網站
Xcode
sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
使用 Apple Silicon 晶片的人需要在 ~/.bashrc
或 ~/.zshrc
裡頭加上 export PATH="/opt/homebrew/bin:$PATH"
並重新啟動終端機,才能找到 brew
指令。
如果有安裝 Oh My Zsh 又想要自動補完 brew 的指令,需要在 ~/.zprofile
加入以下文字:
eval $(/opt/homebrew/bin/brew shellenv)
FPATH="$(brew --prefix)/share/zsh/site-functions:${FPATH}"
brew install git
brew install git-lfs
Ruby
我用 rbenv
來管理我的 Ruby 版本與環境。
brew install rbenv
rbenv install 3.1.2 # 沒特殊需求的話可以指定最新穩定版
rbenv rehash
rbenv global 3.1.2
如果安裝過程有遇到 permission denied 的問題(我在 M1 晶片有遇到),可以嘗試用這個指令修複:sudo chown -R "$(whoami)":admin /usr/local/var
。
另外記得在 ~/.bashrc
或 ~/.zshrc
檔案結尾加入以下設定,然後重新登入。
export RBENV_ROOT=/usr/local/var/rbenv
if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi
gem install cocoapods
我的電腦裝的軟體不多,這邊列出的都是我比較常用的。
我以前常用的是 Google Chrome,現在改用 Vivaldi,兩個都符合我的需求:「多組帳號切換」、「設定可同步」、「套件多」。我不選擇 Firefox 的原因是因為它的帳號切換不好用。
另外同樣是基於 Chromium 的還有 Microsoft Edge、Brave 跟 Sidekick,都有各自的特色,也都能使用 Google Chrome Extension。我自己必備的 Extension 有記錄在這篇文章。
最近發現一款新的瀏覽器叫做 Orion,它就像是更重視隱私的 Safari + 支援 Chrome/Firefox extensions,是個有趣的嘗試。
除了用 LINE 跟親友聯絡之外,工作上還需要用到 Slack 跟 Skype,有時還會用 Telegram 跟 Facebook Messenger 聊天打屁。開一大堆視窗只為了傳訊息讓我覺得很蠢,所以我通常使用 Ferdium 這個整合型通訊工具,類似的整合工具還有 Franz 跟 Station。
我的文字跟程式碼編輯器首選是 Visual Studio Code,理由是它「速度夠快」、「界面友好」、「套件多」,我必備的 VSCode 套件有記錄在這篇文章。之前我有用過 Sublime Text,它真的很快,但因為它界面不夠友善而我懶得折騰所以放棄了。
工程師一定要用的還有 Markdown 編輯器,我強烈推薦 Typora,它的所見即所得以及多種佈景主題讓我用過就再也離不開,後起之秀 妙言 看起來也很不錯,簡單輕巧是它的特色。
內建的 Terminal 不夠好用,所以我都會改用 iTerm,配合 oh-my-zsh 使用 Zsh shell。如果需要更強大的 Terminal,也可以試試看 Tabby,它不只跨平台,而且還支援了 SSH / Serial / Telnet 連線。
我都用 Git 做版本控制。Git 很強大但也很難用(雖然常用的指令就那麼幾個),還好它有很多免費或商用的 GUI。我用的是 Fork,它的使用介面非常友善,並且操作非常流暢。其他比較有名氣的還有 SourceTree、Tower、SmartGit、以及 GitKraken。
我用 Dash 觀看 API 文件與管理程式碼片段,用 Postman 管理與呼叫 API。
如果要檢查 App 的 UI 的話,平時 Xcode 內建的工具就很夠用了,若需要進階一點可以考慮免費的 Lookin,或是需要付費的 Reveal 或 Sherlock。
有些不常用的需求,可以使用一些免費的線上工具解決。
因為 Xcode 只支援 RSA / DSA / ECDSA 這三種演算法的 SSH key,但 GitHub 不支援 RSA 跟 DSA 了,所以我們只剩下 ECDSA 可以用。
如果當時按照 GitHub 的文件建立 SSH key,它很有可能是 ED25519,這個演算法 Xcode 認不得,所以我們要新增一個新的 SSH key。
]]>因為 Xcode 只支援 RSA / DSA / ECDSA 這三種演算法的 SSH key,但 GitHub 不支援 RSA 跟 DSA 了,所以我們只剩下 ECDSA 可以用。
如果當時按照 GitHub 的文件建立 SSH key,它很有可能是 ED25519,這個演算法 Xcode 認不得,所以我們要新增一個新的 SSH key。
新增 SSH key 的方法可以參考 GitHub 的文件,唯二要修改的地方是
ssh-keygen -t ed25519 -C "your_email@example.com"
改成 ssh-keygen -t ecdsa -b 521 -C "your_email@example.com"
id_ed25519
改成 id_ecdsa
然後參考另一份 GitHub 文件,把 SSH key 加到你的 GitHub account。
從 Xcode Preference -> Accounts
新增一個 GitHub account,
建立帳號之後,記得把 SSH Key 設為剛剛建立的 ECDSA。這樣就完成啦。
]]>WKWebView
呈現網頁內容,除了單純的呈現之外,彼此的互動也是不可或缺的一環。這篇文章將會簡單介紹該如何達成網頁與 iOS 原生程式碼之間的雙向溝通。
]]>WKWebView
呈現網頁內容,除了單純的呈現之外,彼此的互動也是不可或缺的一環。這篇文章將會簡單介紹該如何達成網頁與 iOS 原生程式碼之間的雙向溝通。
我們事先要約定好可被呼叫的函式名稱,以及可接受的參數格式,然後在 Web 呼叫 Javascript 程式如下:
window.webkit.messageHandlers.myAwesomeHandler.postMessage({
param1: "value1",
param2: "value2"
})
根據蘋果官方文件的說明,可被呼叫的函式都要放在 window.webkit.messageHandlers
物件底下,其中 myAwesomeHandler
是雙方約定好的函式名稱,postMessage
要傳的則是約定好的參數格式,最常見的格式就是 JSON Object
跟 String
。
上一段提到 Web 要呼叫的 handler 是雙方約定好的函式名稱,我們可以像這樣列舉所有支援的 handlers:
private enum WebMessageHandler: String, CaseIterable {
case myAwesomeHandler
case iapHandler
case closeHandler
}
假設我們自訂一個 UIViewController
來顯示 WKWebView
,在 viewDidLoad()
裡頭可用以下做法告訴 webView 有哪些 message handlers 能夠被呼叫:
let configuration = WKWebViewConfiguration()
for handler in WebMessageHandler.allCases {
configuration.userContentController.add(self, name: handler.rawValue)
}
webView = WKWebView(frame: .zero, configuration: configuration)
view.addSubview(webView)
另外要注意的是,因為 userContentController
會持有 message handler,所以要記得在適當時機呼叫 removeScriptMessageHandler(forName name: String)
,這樣才不會產生 retain-cycle 造成 memory leak。或者也可以參考這個 stack overflow 的討論使用其他方法解決。
Note:
除了列出所有會用到的函式之外,還有另一種作法是只約定一個函式,再根據傳過來的參數判斷要作什麼事情。
別忘了在我們自訂的 UIViewController
要遵守 WKScriptMessageHandler
協定,這樣才能回應 Web 的請求:
extension MyUIViewController: WKScriptMessageHandler {
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let handler = WebMessageHandler(rawValue: message.name) else { return }
switch handler {
case .myAwesomeHandler:
guard let dict = message.body as? [String: Any],
let param1 = dict["param1"] as? String,
let param2 = dict["param2"] as? String else {
return
}
// Do some awesome stuff.
case .iapHandler:
// Open IAP page.
case .closeHandler:
// Close the web view.
}
}
}
當我們處理完畢 Web 的請求之後,要如何把結果傳回去呢?一個很常見的作法是透過 JSON String,它的程式碼大致上像這樣:
let data: [String: Any] = [
"type": "userInfo",
"value": [
"name": "John Appleseed",
"id": "johnappleseed12345678"
]
]
guard let json = try? JSONSerialization.data(withJSONObject: data, options: [.withoutEscapingSlashes]),
let jsonString = String(data: json, encoding: .utf8)
else {
return
}
let javascript = "window.actions.MessageFromNative('\(jsonString)')"
webView.evaluateJavaScript(javascript, completionHandler: nil)
其中 window.actions.MessageFromNative()
是雙方事先約定好在 Web 端要實作的 Javascript 函式,如此一來 Native 只要把資料轉成 JSON String 再傳過去即可,當然 JSON 的格式也是事先約定好的。
Note:
如果是傳 JSON String 的話,很有可能需要開啟
.withoutEscapingSlashes
設定,這樣對方才不會收到反斜線跳脫字元。除了
JSONSerialization
也可以用JSONEncoder
,挑適合自己情境的來使用即可。
以上簡單的說明了 Native Code 跟 Web 之間的交互過程,以此為基礎再加上一些創造力,就可以玩出很多花樣了!
]]>Material Icon Theme
幫各種不同類型的檔案加上圖示。
One Dark Pro
One Dark Pro 主題,寫程式時我喜歡用暗色主題。
C/C++
支援 C/C++ 程式語言,包含 IntelliSense 跟 debug。
Better C++ Syntax
更完整的 C++ 語法高亮度。
Swift
支援 Swift 程式語言。
Ruby
支援 Ruby 程式語言與 debug。
vscode-gitignore-syntax
幫 .gitignore
檔加上語法高亮度。
Syntax Xcode Project Data
幫 Xcode 的 project.pbxproj
專案檔加上語法高亮度。
PropertyList
幫 .plist
檔加上語法高亮度。
Git Graph
完整的 Git client,功能齊全、介面美觀、操作順手,非常值得一試。
Prettier - Code formatter
重整程式碼的工具,支援超多種程式語言。
Sort JSON objects
排序 JSON 檔內的 keys。
Fold Plus
新增許多實用的程式碼折疊 / 展開指令,對於瀏覽很多行數的程式碼非常有用。
vscode-mindmap
建立一個 .km
或 .km.svg
檔就可以開始畫心智圖,雖然缺少群組或關聯線等功能,但已經符合大多數的使用情況了。
Draw.io Integration
將 Draw.io 整合到 VSCode 編輯器,支援 .drawio
/ .dio
/ .drawio.svg
/ .drawio.png
檔案。
Markdown All in One
幫內建的 Markdown 加上許多實用的功能,如果偏好使用純文字環境,那這個工具就很適合你。
Markdown Editor
所見即所得的 Markdown 編輯器,也可以隨時在編輯器跟純文字之間切換。
Markdown Preview Github Styling
將內建的 Markdown Preview 改成 Github 的樣式,對於把專案放在 Github 的人來說很方便。
Compare View
開啟一個比對視窗,可以比對兩份文字。
Whitespace Formatter
移除多餘的結尾空白跟空白列,也可以把縮排轉換成 Tab
或 Space
。
Sort lines
排序選取的文字。
CodeSnap
將選取的文字轉成圖片,方便分享到網路上。
Select Line Status Bar
在狀態列顯示選取了幾行文字。