mirror of
https://github.com/ada-dmitry/ada-dmitry.github.io.git
synced 2026-09-24 01:10:35 +00:00
Упрощение генерации графа заметок: удалены неиспользуемые методы и улучшена обработка узлов и рёбер. Обновлён формат сохранения данных в assets/js/graph-data.json.
This commit is contained in:
+30
-88
@@ -1,108 +1,50 @@
|
|||||||
# _plugins/note_graph.rb
|
# _plugins/note_graph.rb
|
||||||
# Генерирует /graph.json с узлами и рёбрами между заметками из коллекции :notes.
|
|
||||||
# Понимает [[target]], [[target|alias]], вложенные папки, alias'ы во front matter:
|
|
||||||
# aliases: ["Короткое имя", "Другое имя"]
|
|
||||||
|
|
||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
module NoteGraph
|
module Jekyll
|
||||||
class Generator < Jekyll::Generator
|
class NoteGraphGenerator < Generator
|
||||||
safe true
|
safe true
|
||||||
priority :low
|
priority :low
|
||||||
|
|
||||||
WIKI_RX = /\[\[([^\]|#]+)(?:#[^\]|]+)?(?:\|[^\]]+)?\]\]/.freeze
|
|
||||||
|
|
||||||
def generate(site)
|
def generate(site)
|
||||||
notes = (site.collections["notes"]&.docs || [])
|
notes = site.collections["notes"].docs
|
||||||
return if notes.empty?
|
|
||||||
|
|
||||||
# Карта идентификаторов заметок -> объект
|
nodes = []
|
||||||
# id = относительный путь внутри _notes без расширения, в нижнем регистре
|
|
||||||
index = {}
|
|
||||||
aliases = {}
|
|
||||||
|
|
||||||
notes.each do |doc|
|
|
||||||
id = norm_id(doc.relative_path) # напр. "it-school/04-auto"
|
|
||||||
index[id] = {
|
|
||||||
"id" => id,
|
|
||||||
"title" => (doc.data["title"] || File.basename(id)),
|
|
||||||
"url" => doc.url
|
|
||||||
}
|
|
||||||
|
|
||||||
# поддержка front matter aliases
|
|
||||||
Array(doc.data["aliases"]).each do |al|
|
|
||||||
aliases[norm_key(al)] = id
|
|
||||||
end
|
|
||||||
|
|
||||||
# ещё можно сопоставлять обычное название файла без папок
|
|
||||||
base = File.basename(id)
|
|
||||||
aliases[norm_key(base)] = id
|
|
||||||
end
|
|
||||||
|
|
||||||
# Узлы
|
|
||||||
nodes = index.values
|
|
||||||
|
|
||||||
# Рёбра
|
|
||||||
links = []
|
links = []
|
||||||
|
|
||||||
notes.each do |doc|
|
notes.each do |note|
|
||||||
src = norm_id(doc.relative_path)
|
# Добавляем узел
|
||||||
content = doc.content.to_s
|
nodes << { id: note.data["title"] || note.basename_without_ext }
|
||||||
|
|
||||||
content.scan(WIKI_RX).each do |m|
|
# Парсим wiki-ссылки [[...]]
|
||||||
raw = m.first # то, что внутри [[ ... ]]
|
content = note.content
|
||||||
# цель без якоря/алиаса и расширения
|
content.scan(/\[\[([^\]|]+)(?:\|[^\]]+)?\]\]/).flatten.each do |target|
|
||||||
target = raw.strip
|
links << {
|
||||||
target = target.sub(/\|.*/, "") # отрезать |alias
|
source: note.data["title"] || note.basename_without_ext,
|
||||||
target = target.sub(/#.*/, "") # отрезать #heading
|
target: target
|
||||||
target = target.sub(/\.md$/i, "") # убрать .md
|
}
|
||||||
|
|
||||||
# 1) прямое совпадение по относительному пути
|
|
||||||
dst = index[norm_id("_notes/#{target}.md")]&.dig("id")
|
|
||||||
# 2) совпадение по alias/названию файла
|
|
||||||
dst ||= aliases[norm_key(target)]
|
|
||||||
next unless dst && index[dst]
|
|
||||||
|
|
||||||
links << { "source" => src, "target" => dst }
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
data = { "nodes" => nodes, "links" => links }
|
graph_hash = { nodes: nodes, links: links }
|
||||||
|
json_str = JSON.pretty_generate(graph_hash)
|
||||||
|
|
||||||
site.static_files << GeneratedJson.new(site, data)
|
site.static_files << GeneratedJson.new(site, json_str)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class GeneratedJson < Jekyll::StaticFile
|
||||||
|
def initialize(site, content)
|
||||||
|
@site = site
|
||||||
|
@content = content
|
||||||
|
super(site, site.dest, "assets/js", "graph-data.json", nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
# нормализуем «ключ»
|
def write(_dest)
|
||||||
def norm_key(s)
|
out_path = @site.in_dest_dir("assets/js/graph-data.json")
|
||||||
s.to_s.downcase.strip.gsub("\\", "/")
|
FileUtils.mkdir_p(File.dirname(out_path))
|
||||||
end
|
File.write(out_path, @content)
|
||||||
|
true
|
||||||
# делаем id из относительного пути документа
|
|
||||||
# "_notes/IT-School/04-auto.md" -> "it-school/04-auto"
|
|
||||||
def norm_id(relative_path)
|
|
||||||
p = relative_path.to_s
|
|
||||||
p = p.sub(%r!^_notes/!i, "")
|
|
||||||
p = p.sub(/\.md$/i, "")
|
|
||||||
p.downcase
|
|
||||||
end
|
|
||||||
|
|
||||||
# Объект статического файла, который кладём в _site/graph.json
|
|
||||||
class GeneratedJson < Jekyll::StaticFile
|
|
||||||
def initialize(site, data)
|
|
||||||
@site = site
|
|
||||||
@base = site.source
|
|
||||||
@dir = "/"
|
|
||||||
@name = "graph.json"
|
|
||||||
@data = data
|
|
||||||
super(site, @base, @dir, @name, nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
def write(dest)
|
|
||||||
out_path = @site.in_dest_dir('assets/js/graph-data.json')
|
|
||||||
FileUtils.mkdir_p(File.dirname(out_path))
|
|
||||||
File.write(out_path, json)
|
|
||||||
true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user