llm-docs-builder 0.12.0 → 1.0.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/.github/workflows/ci.yml +25 -7
- data/.github/workflows/docker.yml +7 -7
- data/.github/workflows/push.yml +3 -3
- data/.rubocop.yml +1 -14
- data/.ruby-version +1 -1
- data/.yard-lint.yml +309 -0
- data/CHANGELOG.md +17 -0
- data/Dockerfile +14 -7
- data/Gemfile +1 -1
- data/Gemfile.lock +33 -58
- data/lib/llm_docs_builder/cli.rb +1 -3
- data/lib/llm_docs_builder/generator.rb +1 -2
- data/lib/llm_docs_builder/html_detector.rb +1 -2
- data/lib/llm_docs_builder/html_to_markdown/figure_code_block_renderer.rb +2 -3
- data/lib/llm_docs_builder/html_to_markdown_converter.rb +33 -1
- data/lib/llm_docs_builder/output_formatter.rb +2 -3
- data/lib/llm_docs_builder/parser.rb +3 -5
- data/lib/llm_docs_builder/text_compressor.rb +4 -5
- data/lib/llm_docs_builder/token_estimator.rb +2 -3
- data/lib/llm_docs_builder/transformers/base_transformer.rb +2 -3
- data/lib/llm_docs_builder/transformers/heading_transformer.rb +21 -10
- data/lib/llm_docs_builder/transformers/link_transformer.rb +15 -3
- data/lib/llm_docs_builder/transformers/whitespace_transformer.rb +1 -2
- data/lib/llm_docs_builder/validator.rb +1 -2
- data/lib/llm_docs_builder/version.rb +1 -1
- data/lib/llm_docs_builder.rb +2 -3
- data/llm-docs-builder.gemspec +4 -3
- data/package-lock.json +331 -0
- data/package.json +9 -0
- data/renovate.json +33 -9
- metadata +13 -9
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
llm-docs-builder (0.
|
|
4
|
+
llm-docs-builder (1.0.0)
|
|
5
5
|
nokogiri (~> 1.17)
|
|
6
6
|
zeitwerk (~> 2.6)
|
|
7
7
|
|
|
@@ -9,49 +9,31 @@ GEM
|
|
|
9
9
|
remote: https://rubygems.org/
|
|
10
10
|
specs:
|
|
11
11
|
ast (2.4.3)
|
|
12
|
-
byebug (12.0.0)
|
|
13
12
|
coderay (1.1.3)
|
|
14
|
-
date (3.5.0)
|
|
15
13
|
diff-lcs (1.6.2)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
irb (1.15.3)
|
|
20
|
-
pp (>= 0.6.0)
|
|
21
|
-
rdoc (>= 4.0.0)
|
|
22
|
-
reline (>= 0.4.2)
|
|
23
|
-
json (2.16.0)
|
|
24
|
-
language_server-protocol (3.17.0.5)
|
|
14
|
+
io-console (0.9.2)
|
|
15
|
+
json (2.21.2)
|
|
16
|
+
language_server-protocol (3.17.0.6)
|
|
25
17
|
lint_roller (1.1.0)
|
|
26
18
|
method_source (1.1.0)
|
|
27
|
-
|
|
19
|
+
mini_portile2 (2.8.9)
|
|
20
|
+
nokogiri (1.19.4)
|
|
21
|
+
mini_portile2 (~> 2.8.2)
|
|
28
22
|
racc (~> 1.4)
|
|
29
|
-
parallel (1.
|
|
30
|
-
parser (3.3.
|
|
23
|
+
parallel (2.1.0)
|
|
24
|
+
parser (3.3.12.0)
|
|
31
25
|
ast (~> 2.4.1)
|
|
32
26
|
racc
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
prettyprint (0.2.0)
|
|
36
|
-
prism (1.6.0)
|
|
37
|
-
pry (0.15.2)
|
|
27
|
+
prism (1.9.0)
|
|
28
|
+
pry (0.16.0)
|
|
38
29
|
coderay (~> 1.1)
|
|
39
30
|
method_source (~> 1.0)
|
|
40
|
-
|
|
41
|
-
byebug (~> 12.0)
|
|
42
|
-
pry (>= 0.13, < 0.16)
|
|
43
|
-
psych (5.2.6)
|
|
44
|
-
date
|
|
45
|
-
stringio
|
|
31
|
+
reline (>= 0.6.0)
|
|
46
32
|
racc (1.8.1)
|
|
47
33
|
rainbow (3.1.1)
|
|
48
|
-
rake (13.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
psych (>= 4.0.0)
|
|
52
|
-
tsort
|
|
53
|
-
regexp_parser (2.11.3)
|
|
54
|
-
reline (0.6.3)
|
|
34
|
+
rake (13.4.2)
|
|
35
|
+
regexp_parser (2.12.0)
|
|
36
|
+
reline (0.7.0)
|
|
55
37
|
io-console (~> 0.5)
|
|
56
38
|
rspec (3.13.2)
|
|
57
39
|
rspec-core (~> 3.13.0)
|
|
@@ -62,56 +44,49 @@ GEM
|
|
|
62
44
|
rspec-expectations (3.13.5)
|
|
63
45
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
64
46
|
rspec-support (~> 3.13.0)
|
|
65
|
-
rspec-mocks (3.13.
|
|
47
|
+
rspec-mocks (3.13.8)
|
|
66
48
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
67
49
|
rspec-support (~> 3.13.0)
|
|
68
|
-
rspec-support (3.13.
|
|
69
|
-
rubocop (1.
|
|
50
|
+
rspec-support (3.13.7)
|
|
51
|
+
rubocop (1.89.0)
|
|
70
52
|
json (~> 2.3)
|
|
71
53
|
language_server-protocol (~> 3.17.0.2)
|
|
72
54
|
lint_roller (~> 1.1.0)
|
|
73
|
-
parallel (
|
|
55
|
+
parallel (>= 1.10)
|
|
74
56
|
parser (>= 3.3.0.2)
|
|
75
57
|
rainbow (>= 2.2.2, < 4.0)
|
|
76
58
|
regexp_parser (>= 2.9.3, < 3.0)
|
|
77
|
-
rubocop-ast (>= 1.
|
|
59
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
78
60
|
ruby-progressbar (~> 1.7)
|
|
79
61
|
unicode-display_width (>= 2.4.0, < 4.0)
|
|
80
|
-
rubocop-ast (1.
|
|
62
|
+
rubocop-ast (1.50.0)
|
|
81
63
|
parser (>= 3.3.7.2)
|
|
82
|
-
prism (~> 1.
|
|
64
|
+
prism (~> 1.7)
|
|
83
65
|
ruby-progressbar (1.13.0)
|
|
84
|
-
simplecov (
|
|
85
|
-
docile (~> 1.1)
|
|
86
|
-
simplecov-html (~> 0.11)
|
|
87
|
-
simplecov_json_formatter (~> 0.1)
|
|
88
|
-
simplecov-html (0.13.2)
|
|
89
|
-
simplecov_json_formatter (0.1.4)
|
|
90
|
-
stringio (3.1.8)
|
|
91
|
-
tsort (0.2.0)
|
|
66
|
+
simplecov (1.1.1)
|
|
92
67
|
unicode-display_width (3.2.0)
|
|
93
68
|
unicode-emoji (~> 4.1)
|
|
94
|
-
unicode-emoji (4.
|
|
95
|
-
|
|
96
|
-
yard
|
|
97
|
-
|
|
69
|
+
unicode-emoji (4.2.0)
|
|
70
|
+
warning (1.6.0)
|
|
71
|
+
yard (0.9.45)
|
|
72
|
+
yard-lint (1.11.0)
|
|
98
73
|
yard (~> 0.9)
|
|
99
74
|
zeitwerk (~> 2.6)
|
|
100
|
-
zeitwerk (2.
|
|
75
|
+
zeitwerk (2.8.3)
|
|
101
76
|
|
|
102
77
|
PLATFORMS
|
|
103
|
-
|
|
78
|
+
ruby
|
|
104
79
|
|
|
105
80
|
DEPENDENCIES
|
|
106
|
-
bundler
|
|
81
|
+
bundler
|
|
107
82
|
llm-docs-builder!
|
|
108
83
|
pry
|
|
109
|
-
pry-byebug
|
|
110
84
|
rake (~> 13.0)
|
|
111
85
|
rspec (~> 3.0)
|
|
112
86
|
rubocop (~> 1.0)
|
|
113
|
-
simplecov (~> 0
|
|
87
|
+
simplecov (~> 1.0)
|
|
88
|
+
warning
|
|
114
89
|
yard-lint
|
|
115
90
|
|
|
116
91
|
BUNDLED WITH
|
|
117
|
-
|
|
92
|
+
4.0.17
|
data/lib/llm_docs_builder/cli.rb
CHANGED
|
@@ -129,8 +129,7 @@ module LlmDocsBuilder
|
|
|
129
129
|
|
|
130
130
|
# Generate llms.txt from documentation directory or file
|
|
131
131
|
#
|
|
132
|
-
# Loads configuration, merges with CLI options, generates llms.txt content,
|
|
133
|
-
# and optionally validates the output.
|
|
132
|
+
# Loads configuration, merges with CLI options, generates llms.txt content, and optionally validates the output.
|
|
134
133
|
#
|
|
135
134
|
# @param options [Hash] command options from parse_options
|
|
136
135
|
# @option options [String] :config path to config file
|
|
@@ -399,7 +398,6 @@ module LlmDocsBuilder
|
|
|
399
398
|
end
|
|
400
399
|
|
|
401
400
|
# Display version information
|
|
402
|
-
#
|
|
403
401
|
def show_version
|
|
404
402
|
puts "llm-docs-builder version #{LlmDocsBuilder::VERSION}"
|
|
405
403
|
end
|
|
@@ -34,8 +34,7 @@ module LlmDocsBuilder
|
|
|
34
34
|
|
|
35
35
|
# Generate llms.txt content from documentation
|
|
36
36
|
#
|
|
37
|
-
# Scans documentation files, extracts metadata, prioritizes them, and builds a formatted
|
|
38
|
-
# llms.txt file.
|
|
37
|
+
# Scans documentation files, extracts metadata, prioritizes them, and builds a formatted llms.txt file.
|
|
39
38
|
#
|
|
40
39
|
# @return [String] generated llms.txt content
|
|
41
40
|
def generate
|
|
@@ -14,8 +14,7 @@ module LlmDocsBuilder
|
|
|
14
14
|
full_html_document?(content)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
# Prepare a snippet of content for HTML detection by removing leading whitespace
|
|
18
|
-
# and build metadata comments.
|
|
17
|
+
# Prepare a snippet of content for HTML detection by removing leading whitespace and build metadata comments.
|
|
19
18
|
#
|
|
20
19
|
# @param content [String]
|
|
21
20
|
# @return [String, nil]
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
module LlmDocsBuilder
|
|
4
4
|
# Provides HTML to Markdown conversion functionality
|
|
5
5
|
#
|
|
6
|
-
# This module contains specialized renderers for converting HTML elements
|
|
7
|
-
#
|
|
8
|
-
# figures, and syntax-highlighted code blocks.
|
|
6
|
+
# This module contains specialized renderers for converting HTML elements to Markdown format, with support for complex
|
|
7
|
+
# structures like tables, figures, and syntax-highlighted code blocks.
|
|
9
8
|
#
|
|
10
9
|
# @api private
|
|
11
10
|
module HtmlToMarkdown
|
|
@@ -120,7 +120,8 @@ module LlmDocsBuilder
|
|
|
120
120
|
text = collapsed_inline_for(element)
|
|
121
121
|
return '' if text.empty?
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
effective_level = effective_heading_level(element, HEADING_LEVEL[tag])
|
|
124
|
+
"#{'#' * effective_level} #{text}"
|
|
124
125
|
when 'blockquote'
|
|
125
126
|
render_blockquote(element)
|
|
126
127
|
when 'pre'
|
|
@@ -641,6 +642,37 @@ module LlmDocsBuilder
|
|
|
641
642
|
out.join("\n\n")
|
|
642
643
|
end
|
|
643
644
|
|
|
645
|
+
# Compute effective heading level adjusted for section nesting
|
|
646
|
+
#
|
|
647
|
+
# When HTML uses nested <section> elements with same-level headings, the inner headings should receive deeper
|
|
648
|
+
# markdown levels. The offset is calculated as the difference between the actual section ancestor count and the
|
|
649
|
+
# expected count for that heading tag (h1 expects 0 sections, h2 expects 1, etc.), capped at heading level 6.
|
|
650
|
+
#
|
|
651
|
+
# @param element [Nokogiri::XML::Element] heading element
|
|
652
|
+
# @param base_level [Integer] HTML heading level (1-6)
|
|
653
|
+
# @return [Integer] effective markdown heading level (1-6)
|
|
654
|
+
def effective_heading_level(element, base_level)
|
|
655
|
+
depth = section_ancestor_count(element)
|
|
656
|
+
offset = [depth - (base_level - 1), 0].max
|
|
657
|
+
[base_level + offset, 6].min
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
# Count the number of <section> ancestor elements
|
|
661
|
+
#
|
|
662
|
+
# @param element [Nokogiri::XML::Element]
|
|
663
|
+
# @return [Integer] number of section ancestors
|
|
664
|
+
def section_ancestor_count(element)
|
|
665
|
+
count = 0
|
|
666
|
+
node = element.parent
|
|
667
|
+
|
|
668
|
+
while node
|
|
669
|
+
count += 1 if node.element? && node.name.downcase == 'section'
|
|
670
|
+
node = node.parent
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
count
|
|
674
|
+
end
|
|
675
|
+
|
|
644
676
|
# Helpers
|
|
645
677
|
|
|
646
678
|
# Normalize whitespace in text
|
|
@@ -3,8 +3,7 @@
|
|
|
3
3
|
module LlmDocsBuilder
|
|
4
4
|
# Formats output for CLI display
|
|
5
5
|
#
|
|
6
|
-
# Provides formatting utilities for displaying comparison results,
|
|
7
|
-
# byte sizes, and numbers in a user-friendly way.
|
|
6
|
+
# Provides formatting utilities for displaying comparison results, byte sizes, and numbers in a user-friendly way.
|
|
8
7
|
#
|
|
9
8
|
# @api private
|
|
10
9
|
class OutputFormatter
|
|
@@ -30,7 +29,7 @@ module LlmDocsBuilder
|
|
|
30
29
|
|
|
31
30
|
# Format number with comma separators for readability
|
|
32
31
|
#
|
|
33
|
-
# @param number [Integer]
|
|
32
|
+
# @param number [Integer] value to format with comma separators
|
|
34
33
|
# @return [String] formatted number with commas
|
|
35
34
|
#
|
|
36
35
|
# @example
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
module LlmDocsBuilder
|
|
4
4
|
# Parses llms.txt files into structured data
|
|
5
5
|
#
|
|
6
|
-
# Reads and parses llms.txt files according to the llms.txt specification,
|
|
7
|
-
#
|
|
8
|
-
# Examples, Optional) with their links.
|
|
6
|
+
# Reads and parses llms.txt files according to the llms.txt specification, extracting the title, description, and
|
|
7
|
+
# structured sections (Documentation, Examples, Optional) with their links.
|
|
9
8
|
#
|
|
10
9
|
# @example Parse an llms.txt file
|
|
11
10
|
# parser = LlmDocsBuilder::Parser.new('llms.txt')
|
|
@@ -109,8 +108,7 @@ module LlmDocsBuilder
|
|
|
109
108
|
|
|
110
109
|
# Represents parsed llms.txt content with structured access to sections
|
|
111
110
|
#
|
|
112
|
-
# Provides convenient access to parsed llms.txt sections including title,
|
|
113
|
-
# description, and link collections.
|
|
111
|
+
# Provides convenient access to parsed llms.txt sections including title, description, and link collections.
|
|
114
112
|
#
|
|
115
113
|
# @example Access parsed content
|
|
116
114
|
# parsed.title # => "My Project"
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
module LlmDocsBuilder
|
|
4
4
|
# Advanced text compression techniques for reducing token count
|
|
5
5
|
#
|
|
6
|
-
# Provides more aggressive text compression methods including stopword removal,
|
|
7
|
-
#
|
|
8
|
-
# aggressive than basic markdown cleanup and should be used carefully.
|
|
6
|
+
# Provides more aggressive text compression methods including stopword removal, duplicate content detection, and
|
|
7
|
+
# sentence deduplication. These methods are more aggressive than basic markdown cleanup and should be used carefully.
|
|
9
8
|
#
|
|
10
9
|
# @example Basic usage
|
|
11
10
|
# compressor = LlmDocsBuilder::TextCompressor.new
|
|
@@ -72,8 +71,8 @@ module LlmDocsBuilder
|
|
|
72
71
|
# Removes common English stopwords that don't carry significant meaning.
|
|
73
72
|
# Preserves code blocks, inline code, and technical terms.
|
|
74
73
|
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
74
|
+
# @deprecated This is an aggressive optimization that may affect readability.
|
|
75
|
+
# Use with caution and test results carefully.
|
|
77
76
|
#
|
|
78
77
|
# @param content [String] text to process
|
|
79
78
|
# @return [String] text with stopwords removed
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
module LlmDocsBuilder
|
|
4
4
|
# Estimates token count for text content using character-based approximation
|
|
5
5
|
#
|
|
6
|
-
# Provides token estimation without requiring external tokenizer dependencies.
|
|
7
|
-
#
|
|
8
|
-
# which works reasonably well for documentation and markdown content.
|
|
6
|
+
# Provides token estimation without requiring external tokenizer dependencies. Uses the common heuristic that ~4
|
|
7
|
+
# characters equals 1 token for English text, which works reasonably well for documentation and markdown content.
|
|
9
8
|
#
|
|
10
9
|
# @example Basic usage
|
|
11
10
|
# estimator = LlmDocsBuilder::TokenEstimator.new
|
|
@@ -3,9 +3,8 @@
|
|
|
3
3
|
module LlmDocsBuilder
|
|
4
4
|
# Provides content transformation functionality
|
|
5
5
|
#
|
|
6
|
-
# This module contains specialized transformers for modifying markdown content,
|
|
7
|
-
#
|
|
8
|
-
# content enhancement for AI consumption.
|
|
6
|
+
# This module contains specialized transformers for modifying markdown content, including cleanup operations, link
|
|
7
|
+
# processing, heading normalization, and content enhancement for AI consumption.
|
|
9
8
|
#
|
|
10
9
|
# @api private
|
|
11
10
|
module Transformers
|
|
@@ -4,9 +4,8 @@ module LlmDocsBuilder
|
|
|
4
4
|
module Transformers
|
|
5
5
|
# Normalizes headings to include hierarchical context
|
|
6
6
|
#
|
|
7
|
-
# Transforms markdown headings to include parent context, making each section
|
|
8
|
-
#
|
|
9
|
-
# are chunked and retrieved independently.
|
|
7
|
+
# Transforms markdown headings to include parent context, making each section self-contained for RAG systems. This
|
|
8
|
+
# is particularly useful when documents are chunked and retrieved independently.
|
|
10
9
|
#
|
|
11
10
|
# @example Basic heading normalization
|
|
12
11
|
# # Configuration
|
|
@@ -51,24 +50,36 @@ module LlmDocsBuilder
|
|
|
51
50
|
next line if in_code_block
|
|
52
51
|
|
|
53
52
|
# Match markdown headings (1-6 hash symbols followed by space and text)
|
|
54
|
-
|
|
53
|
+
# Supports optional ATX closing hashes (e.g., "## Title ##")
|
|
54
|
+
heading_match = line.match(/^(#+)\s+(.+?)(?:\s+#+)?\s*$/)
|
|
55
55
|
|
|
56
|
-
if heading_match && heading_match[1].
|
|
57
|
-
level = heading_match[1].
|
|
56
|
+
if heading_match && heading_match[1].length.between?(1, 6)
|
|
57
|
+
level = heading_match[1].length
|
|
58
58
|
title = heading_match[2].strip
|
|
59
59
|
|
|
60
60
|
# Update heading stack to current level
|
|
61
61
|
heading_stack = heading_stack[0...level - 1]
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
# Compute the effective heading level. When same-level headings
|
|
64
|
+
# are nested under a parent (e.g., two consecutive ## headings),
|
|
65
|
+
# the child must receive a deeper markdown level so the output
|
|
66
|
+
# hierarchy is correct.
|
|
67
|
+
effective_level = if heading_stack.empty?
|
|
68
|
+
level
|
|
69
|
+
else
|
|
70
|
+
[heading_stack.last[:effective_level] + 1, level].max
|
|
71
|
+
end
|
|
72
|
+
effective_level = [effective_level, 6].min
|
|
73
|
+
|
|
74
|
+
heading_stack << { title: title, effective_level: effective_level }
|
|
63
75
|
|
|
64
76
|
# Build hierarchical heading
|
|
65
77
|
if level == 1
|
|
66
78
|
# H1 stays as-is (top level)
|
|
67
79
|
line
|
|
68
80
|
else
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
"#{'#' * level} #{hierarchical_title}\n"
|
|
81
|
+
hierarchical_title = heading_stack.map { |e| e[:title] }.join(separator)
|
|
82
|
+
"#{'#' * effective_level} #{hierarchical_title}\n"
|
|
72
83
|
end
|
|
73
84
|
else
|
|
74
85
|
line
|
|
@@ -4,8 +4,7 @@ module LlmDocsBuilder
|
|
|
4
4
|
module Transformers
|
|
5
5
|
# Transformer for link-related operations
|
|
6
6
|
#
|
|
7
|
-
# Handles expansion of relative links to absolute URLs and
|
|
8
|
-
# conversion of HTML URLs to markdown format.
|
|
7
|
+
# Handles expansion of relative links to absolute URLs and conversion of HTML URLs to markdown format.
|
|
9
8
|
#
|
|
10
9
|
# @api public
|
|
11
10
|
class LinkTransformer
|
|
@@ -30,6 +29,10 @@ module LlmDocsBuilder
|
|
|
30
29
|
|
|
31
30
|
private
|
|
32
31
|
|
|
32
|
+
# URI schemes that must never be treated as relative paths when expanding
|
|
33
|
+
# links with a base URL (kept in sync with the converter's safe schemes)
|
|
34
|
+
ABSOLUTE_URL_SCHEMES = %w[http https mailto ftp tel].freeze
|
|
35
|
+
|
|
33
36
|
# Expand relative links to absolute URLs
|
|
34
37
|
#
|
|
35
38
|
# @param content [String] markdown content
|
|
@@ -40,7 +43,7 @@ module LlmDocsBuilder
|
|
|
40
43
|
text = ::Regexp.last_match(1)
|
|
41
44
|
url = ::Regexp.last_match(2)
|
|
42
45
|
|
|
43
|
-
if url.start_with?('http://', 'https://', '//', '#')
|
|
46
|
+
if url.start_with?('http://', 'https://', '//', '#') || absolute_url_scheme?(url)
|
|
44
47
|
match
|
|
45
48
|
else
|
|
46
49
|
clean_url = url.gsub(%r{^\./}, '')
|
|
@@ -50,6 +53,15 @@ module LlmDocsBuilder
|
|
|
50
53
|
end
|
|
51
54
|
end
|
|
52
55
|
|
|
56
|
+
# Check whether a link target uses a known absolute URI scheme
|
|
57
|
+
#
|
|
58
|
+
# @param url [String] link target
|
|
59
|
+
# @return [Boolean] true when the target already carries its own scheme
|
|
60
|
+
def absolute_url_scheme?(url)
|
|
61
|
+
scheme = url.split(':', 2).first.to_s
|
|
62
|
+
ABSOLUTE_URL_SCHEMES.include?(scheme)
|
|
63
|
+
end
|
|
64
|
+
|
|
53
65
|
# Convert HTML URLs to markdown format
|
|
54
66
|
#
|
|
55
67
|
# @param content [String] markdown content
|
|
@@ -4,8 +4,7 @@ module LlmDocsBuilder
|
|
|
4
4
|
module Transformers
|
|
5
5
|
# Transformer for whitespace normalization
|
|
6
6
|
#
|
|
7
|
-
# Reduces excessive blank lines and trailing whitespace to make
|
|
8
|
-
# content more compact for LLM consumption.
|
|
7
|
+
# Reduces excessive blank lines and trailing whitespace to make content more compact for LLM consumption.
|
|
9
8
|
#
|
|
10
9
|
# @api public
|
|
11
10
|
class WhitespaceTransformer
|
|
@@ -56,8 +56,7 @@ module LlmDocsBuilder
|
|
|
56
56
|
|
|
57
57
|
# Validate content and return result
|
|
58
58
|
#
|
|
59
|
-
# Runs all validation checks, populates {#errors} array, and returns whether
|
|
60
|
-
# the content is valid.
|
|
59
|
+
# Runs all validation checks, populates {#errors} array, and returns whether the content is valid.
|
|
61
60
|
#
|
|
62
61
|
# @return [Boolean] true if content is valid, false otherwise
|
|
63
62
|
def validate!
|
data/lib/llm_docs_builder.rb
CHANGED
|
@@ -13,9 +13,8 @@ loader.setup
|
|
|
13
13
|
|
|
14
14
|
# Build and optimize documentation for LLMs
|
|
15
15
|
#
|
|
16
|
-
# This gem provides tools for generating llms.txt files and transforming markdown
|
|
17
|
-
#
|
|
18
|
-
# preserving essential documentation content.
|
|
16
|
+
# This gem provides tools for generating llms.txt files and transforming markdown documentation to be AI-friendly. It
|
|
17
|
+
# can reduce token consumption by 67-95% while preserving essential documentation content.
|
|
19
18
|
#
|
|
20
19
|
# @api public
|
|
21
20
|
module LlmDocsBuilder
|
data/llm-docs-builder.gemspec
CHANGED
|
@@ -20,13 +20,14 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
|
|
21
21
|
spec.homepage = 'https://github.com/mensfeld/llm-docs-builder'
|
|
22
22
|
spec.license = 'MIT'
|
|
23
|
-
spec.required_ruby_version = '>= 3.
|
|
23
|
+
spec.required_ruby_version = '>= 3.3'
|
|
24
24
|
|
|
25
25
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
|
26
26
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
27
27
|
spec.metadata['source_code_uri'] = 'https://github.com/mensfeld/llm-docs-builder'
|
|
28
28
|
spec.metadata['changelog_uri'] = 'https://github.com/mensfeld/llm-docs-builder/blob/master/CHANGELOG.md'
|
|
29
29
|
spec.metadata['documentation_uri'] = 'https://github.com/mensfeld/llm-docs-builder'
|
|
30
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/mensfeld/llm-docs-builder/issues'
|
|
30
31
|
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
31
32
|
|
|
32
33
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|test)/}) }
|
|
@@ -38,9 +39,9 @@ Gem::Specification.new do |spec|
|
|
|
38
39
|
spec.add_dependency 'nokogiri', '~> 1.17'
|
|
39
40
|
spec.add_dependency 'zeitwerk', '~> 2.6'
|
|
40
41
|
|
|
41
|
-
spec.add_development_dependency 'bundler'
|
|
42
|
+
spec.add_development_dependency 'bundler'
|
|
42
43
|
spec.add_development_dependency 'rake', '~> 13.0'
|
|
43
44
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
44
45
|
spec.add_development_dependency 'rubocop', '~> 1.0'
|
|
45
|
-
spec.add_development_dependency 'simplecov', '~> 0
|
|
46
|
+
spec.add_development_dependency 'simplecov', '~> 1.0'
|
|
46
47
|
end
|