ligarb 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/ligarb/builder.rb +17 -0
- data/lib/ligarb/chapter.rb +41 -4
- data/lib/ligarb/cli.rb +27 -0
- data/lib/ligarb/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 20b29dff31e22937e2ab71a7011d1ed2fb193c8717753c7a23500767645807f1
|
|
4
|
+
data.tar.gz: be6404f8dccb7cea765b8635f9663b57f0c23e73253a29da6ac49ca0017baae1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9ca9e973840571772b22b493ddfbc15b87c844abf05e84c2805c3d63ede347a3e245745e5bab2b8d2a3cb8d7b13b3c6c9d94f70b2d5c6d572eefadc11a839d64
|
|
7
|
+
data.tar.gz: 98f30f871f31b96331ebac03a4e0bb85690e612e14dd0412592ff2a1400a897698807d206f851143561e27bd384d32273517531708c2f1af7ee59aaaedf33c17
|
data/lib/ligarb/builder.rb
CHANGED
|
@@ -16,6 +16,7 @@ module Ligarb
|
|
|
16
16
|
structure = load_structure
|
|
17
17
|
|
|
18
18
|
all_chapters = collect_all_chapters(structure)
|
|
19
|
+
resolve_cross_references(all_chapters)
|
|
19
20
|
assign_relative_paths(all_chapters) if @config.repository
|
|
20
21
|
|
|
21
22
|
assets = AssetManager.new(@config.output_path)
|
|
@@ -106,6 +107,22 @@ module Ligarb
|
|
|
106
107
|
end
|
|
107
108
|
end
|
|
108
109
|
|
|
110
|
+
def resolve_cross_references(all_chapters)
|
|
111
|
+
chapter_map = {}
|
|
112
|
+
all_chapters.each do |ch|
|
|
113
|
+
abs_path = File.expand_path(ch.instance_variable_get(:@path))
|
|
114
|
+
chapter_map[abs_path] = {
|
|
115
|
+
slug: ch.slug,
|
|
116
|
+
chapter: ch,
|
|
117
|
+
headings: ch.headings.each_with_object({}) { |h, map| map[h.id] = h }
|
|
118
|
+
}
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
all_chapters.each do |ch|
|
|
122
|
+
ch.resolve_cross_references!(chapter_map)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
109
126
|
def assign_relative_paths(chapters)
|
|
110
127
|
git_root = find_git_root(@config.base_dir)
|
|
111
128
|
chapters.each do |ch|
|
data/lib/ligarb/chapter.rb
CHANGED
|
@@ -5,6 +5,8 @@ require "kramdown-parser-gfm"
|
|
|
5
5
|
|
|
6
6
|
module Ligarb
|
|
7
7
|
class Chapter
|
|
8
|
+
class CrossReferenceError < StandardError; end
|
|
9
|
+
|
|
8
10
|
attr_reader :title, :slug, :html, :headings, :number, :appendix_letter, :index_entries
|
|
9
11
|
attr_accessor :part_title, :cover, :relative_path
|
|
10
12
|
|
|
@@ -43,6 +45,44 @@ module Ligarb
|
|
|
43
45
|
@cover
|
|
44
46
|
end
|
|
45
47
|
|
|
48
|
+
def self.generate_id(text)
|
|
49
|
+
text.downcase
|
|
50
|
+
.gsub(/[^\p{L}\p{N}\s_-]/u, "")
|
|
51
|
+
.strip
|
|
52
|
+
.gsub(/\s+/, "-")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def resolve_cross_references!(chapter_map)
|
|
56
|
+
source_dir = File.dirname(@path)
|
|
57
|
+
|
|
58
|
+
@html = @html.gsub(%r{<a\s+href="((?!https?://)[^"]+\.md)(?:#([^"]*))?">(.*?)</a>}m) do
|
|
59
|
+
href_path = $1
|
|
60
|
+
fragment = $2
|
|
61
|
+
link_text = $3
|
|
62
|
+
|
|
63
|
+
target_path = File.expand_path(href_path, source_dir)
|
|
64
|
+
entry = chapter_map[target_path]
|
|
65
|
+
unless entry
|
|
66
|
+
raise CrossReferenceError, "cross-reference target not found: #{href_path} (from #{File.basename(@path)})"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
if fragment && !fragment.empty?
|
|
70
|
+
normalized = self.class.generate_id(fragment)
|
|
71
|
+
heading = entry[:headings][normalized]
|
|
72
|
+
unless heading
|
|
73
|
+
raise CrossReferenceError, "cross-reference heading not found: #{href_path}##{fragment} (from #{File.basename(@path)})"
|
|
74
|
+
end
|
|
75
|
+
anchor = "#{entry[:slug]}--#{heading.id}"
|
|
76
|
+
text = link_text.empty? ? heading.display_text : link_text
|
|
77
|
+
else
|
|
78
|
+
anchor = entry[:slug]
|
|
79
|
+
text = link_text.empty? ? entry[:chapter].display_title : link_text
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
%(<a href="##{anchor}">#{text}</a>)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
46
86
|
def display_title
|
|
47
87
|
if @appendix_letter
|
|
48
88
|
"#{@appendix_letter}. #{@title}"
|
|
@@ -96,10 +136,7 @@ module Ligarb
|
|
|
96
136
|
end
|
|
97
137
|
|
|
98
138
|
def generate_id(text)
|
|
99
|
-
text
|
|
100
|
-
.gsub(/[^\p{L}\p{N}\s_-]/u, "") # keep letters (any script), digits, spaces, _, -
|
|
101
|
-
.strip
|
|
102
|
-
.gsub(/\s+/, "-")
|
|
139
|
+
self.class.generate_id(text)
|
|
103
140
|
end
|
|
104
141
|
|
|
105
142
|
def apply_heading_ids(html)
|
data/lib/ligarb/cli.rb
CHANGED
|
@@ -374,6 +374,33 @@ module Ligarb
|
|
|
374
374
|
- CAUTION: red (stop)
|
|
375
375
|
- IMPORTANT: purple (exclamation)
|
|
376
376
|
|
|
377
|
+
== Cross-References ==
|
|
378
|
+
|
|
379
|
+
Link to other chapters or headings using standard Markdown relative links.
|
|
380
|
+
ligarb resolves .md file references to internal anchors in the single-page
|
|
381
|
+
output.
|
|
382
|
+
|
|
383
|
+
Syntax:
|
|
384
|
+
|
|
385
|
+
[link text](other-chapter.md) Link to a chapter
|
|
386
|
+
[link text](other-chapter.md#Heading) Link to a specific heading
|
|
387
|
+
[](other-chapter.md) Auto-fill with chapter title
|
|
388
|
+
[](other-chapter.md#Heading) Auto-fill with heading text
|
|
389
|
+
|
|
390
|
+
The .md path is resolved relative to the current Markdown file's directory.
|
|
391
|
+
The heading fragment is matched against heading IDs (case-insensitive,
|
|
392
|
+
normalized the same way heading slugs are generated).
|
|
393
|
+
|
|
394
|
+
When the link text is empty, ligarb fills it with the target's display text:
|
|
395
|
+
- Chapter link: the chapter's display title (e.g. "3. Config Guide")
|
|
396
|
+
- Heading link: the heading's display text (e.g. "3.2 Setup")
|
|
397
|
+
|
|
398
|
+
If a referenced chapter or heading does not exist, the build fails with an
|
|
399
|
+
error message indicating the broken reference and its source file.
|
|
400
|
+
|
|
401
|
+
External URLs ending in .md (e.g. https://example.com/README.md) are not
|
|
402
|
+
affected — only relative paths are resolved.
|
|
403
|
+
|
|
377
404
|
== Previous/Next Navigation ==
|
|
378
405
|
|
|
379
406
|
Each chapter displays Previous and Next navigation links at the bottom.
|
data/lib/ligarb/version.rb
CHANGED