iT邦幫忙

2022 iThome 鐵人賽

DAY 4
0
自我挑戰組

Blog 掛掉時在做什麼?有沒有空?可以來重建嗎?系列 第 4

如何用 SSG 產生 Bi-Directional Link (雙向連結)?

  • 分享至 

  • xImage
  •  

在 Day 2 很讓我驚豔的是有人在 Jekyll Theme 中實作了 Backlink,所以今天就來研究他怎麼做到的。你可以在這個專案的 _includes/backlinks.html 或是透過該檔案在 Github 的頁面讀取原始碼。

透過原始碼,我們可以發現它的結構大概是如以下虛擬碼所示:

let all_nodes = site.notes + site.posts + site.pages

calculateLinkCount()

func calculateLinkCount()
  for all_nodes as node
    if node.link !== current_node.link	
      if node.content contains current_node.title
        count++
  return count
end

發現其實他只是透過遍歷這個網站所有節點 (包括文章、筆記、頁面) 的內文,確認是否含有與該篇文章相同標題的文字來判斷。非常簡單的做法,但因為他會在遍歷所有文章時,執行這段程式,所以要完成所有節點的雙向連結的複雜度是 O(n^2),在日後數量增加後,效能上可能會開始趨緩。

另外找了一個專案 Gatsby Garden,與 Jekyll Garden 相似,但是是實作在 Gastby.js 上,在專案的 gatsby-node.js 或是透過 該檔案在 Github 的頁面讀取原始碼。

透過原始碼,我們可以發現它的結構大概是如以下虛擬碼所示:

let all_nodes = site.notes + site.posts + site.pages
let all_nodes_by_title = {}
let referred_by = {}
let refers_to = {}

for all_nodes as node
  let outgoingLinks = findReferences(node.content)
  
  allNotesByTitle[node.title] = node
  refers_to[node.title] = outgoingLinks

  for outgoingLinks as link_title
    if referred_by[link_title]
      referred_by[link_title] = []
    referredBy[link_title].push(node)

在這個實作則是先遍歷所有節點,並透過 findReferences() 搜尋內文中是否有 [[title]] 的特徵,將其加入預先宣告好的陣列作為索引供之後使用。如此複雜度大約為 O(n),會比上面的做法再好。

我也好奇我慣用的 Obsidian 是如何實作這方面的機制,但因為他不是開源專案,所以難以得知了。目前透過這個研究,我們大概知道未來要實作 Bi-Directional Link (雙向連結) 或是 Back Link (反向連結) 的功能時,大致可以怎麼做了。


上一篇
什麼是 Digital Garden?
下一篇
Blog 上是否只展現完美的自己?還是該正視自己有所未知?
系列文
Blog 掛掉時在做什麼?有沒有空?可以來重建嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言