yard-yaml 0.1.0 → 0.1.2
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +50 -1
- data/CITATION.cff +6 -6
- data/CONTRIBUTING.md +66 -31
- data/FUNDING.md +1 -1
- data/LICENSE.md +11 -0
- data/README.md +123 -885
- data/certs/pboling.pem +27 -0
- data/lib/yard/yaml/converter.rb +88 -11
- data/lib/yard/yaml/emitter.rb +28 -11
- data/lib/yard/yaml/plugin.rb +71 -4
- data/lib/yard/yaml/tag_renderer.rb +1 -1
- data/lib/yard/yaml/tags.rb +3 -7
- data/lib/yard/yaml/version.rb +2 -2
- data/lib/yard/yaml.rb +21 -9
- data/lib/yard-yaml.rb +3 -0
- data/sig/yard/yaml/version.rbs +8 -0
- data.tar.gz.sig +0 -0
- metadata +52 -40
- metadata.gz.sig +0 -0
- data/LICENSE.txt +0 -21
- data/REEK +0 -0
data/certs/pboling.pem
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
|
2
|
+
MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
|
|
3
|
+
ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
|
|
4
|
+
A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
|
|
5
|
+
DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
|
|
6
|
+
LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
|
|
7
|
+
uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
|
|
8
|
+
LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
|
|
9
|
+
mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
|
|
10
|
+
coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
|
|
11
|
+
FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
|
|
12
|
+
yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
|
|
13
|
+
to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
|
|
14
|
+
qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
|
|
15
|
+
fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
|
|
16
|
+
HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
|
|
17
|
+
A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
|
|
18
|
+
ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
|
|
19
|
+
wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
|
|
20
|
+
L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
|
|
21
|
+
GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
|
|
22
|
+
kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
|
|
23
|
+
QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
|
|
24
|
+
0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
|
|
25
|
+
DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
|
|
26
|
+
L9nRqA==
|
|
27
|
+
-----END CERTIFICATE-----
|
data/lib/yard/yaml/converter.rb
CHANGED
|
@@ -12,10 +12,17 @@ module Yard
|
|
|
12
12
|
#
|
|
13
13
|
# Note: We intentionally keep the contract minimal and stable. Tests stub the backend.
|
|
14
14
|
class Converter
|
|
15
|
+
BACKEND_STATE = {backend: nil}
|
|
16
|
+
BACKEND_MUTEX = Mutex.new
|
|
17
|
+
|
|
15
18
|
class << self
|
|
16
19
|
# Assignable backend for dependency injection in tests.
|
|
17
|
-
#
|
|
18
|
-
|
|
20
|
+
# Preferred backends respond to `to_markdown(yaml, options:)`. Legacy
|
|
21
|
+
# test backends may respond to `convert(yaml, options)` and return a
|
|
22
|
+
# Hash with :html, :title, :description, and :meta keys.
|
|
23
|
+
def backend=(backend)
|
|
24
|
+
BACKEND_MUTEX.synchronize { BACKEND_STATE[:backend] = backend }
|
|
25
|
+
end
|
|
19
26
|
|
|
20
27
|
# Convert a YAML string into an HTML result.
|
|
21
28
|
#
|
|
@@ -34,49 +41,119 @@ module Yard
|
|
|
34
41
|
# @param config [Yard::Yaml::Config]
|
|
35
42
|
# @return [Hash]
|
|
36
43
|
def from_file(path, options = {}, config: Yard::Yaml.config)
|
|
37
|
-
content = read_file(path)
|
|
44
|
+
content = read_file(path, config: config)
|
|
38
45
|
return empty_result if content.nil?
|
|
39
46
|
run_convert(content, options.merge(source_path: path.to_s), config)
|
|
40
47
|
end
|
|
41
48
|
|
|
42
49
|
# Backend accessor with auto-discovery.
|
|
43
50
|
def backend
|
|
44
|
-
|
|
51
|
+
configured_backend = BACKEND_MUTEX.synchronize { BACKEND_STATE[:backend] }
|
|
52
|
+
return configured_backend if configured_backend
|
|
53
|
+
|
|
45
54
|
begin
|
|
46
55
|
require "yaml/converter"
|
|
47
56
|
rescue LoadError
|
|
48
57
|
# ignore; backend may be set by tests
|
|
49
58
|
end
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
|
|
60
|
+
BACKEND_MUTEX.synchronize do
|
|
61
|
+
BACKEND_STATE[:backend] ||= ::Yaml::Converter if defined?(::Yaml) && ::Yaml.const_defined?(:Converter)
|
|
52
62
|
end
|
|
53
63
|
end
|
|
54
64
|
|
|
55
65
|
private
|
|
56
66
|
|
|
57
|
-
def read_file(path)
|
|
58
|
-
File.
|
|
67
|
+
def read_file(path, config: Yard::Yaml.config)
|
|
68
|
+
raw = File.binread(path.to_s)
|
|
69
|
+
if binary_content?(raw)
|
|
70
|
+
handle_error(Yard::Yaml::Error.new("binary file not supported"), strict: config.strict, context: path.to_s)
|
|
71
|
+
return
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
content = raw.dup.force_encoding(Encoding::UTF_8)
|
|
75
|
+
return content if content.valid_encoding?
|
|
76
|
+
|
|
77
|
+
if config.strict
|
|
78
|
+
handle_error(Yard::Yaml::Error.new("invalid UTF-8 bytes in file"), strict: true, context: path.to_s)
|
|
79
|
+
return
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
handle_error(
|
|
83
|
+
Yard::Yaml::Error.new("invalid UTF-8 bytes in file; replaced invalid sequences"),
|
|
84
|
+
strict: false,
|
|
85
|
+
context: path.to_s,
|
|
86
|
+
)
|
|
87
|
+
content.scrub
|
|
59
88
|
rescue Errno::ENOENT => e
|
|
60
|
-
handle_error(e, strict:
|
|
89
|
+
handle_error(e, strict: config.strict, context: "missing file: #{path}")
|
|
61
90
|
nil
|
|
62
91
|
end
|
|
63
92
|
|
|
93
|
+
def binary_content?(raw)
|
|
94
|
+
sample = raw.byteslice(0, 4096) || "".b
|
|
95
|
+
return true if sample.include?("\x00")
|
|
96
|
+
return false if sample.empty?
|
|
97
|
+
|
|
98
|
+
control_bytes = sample.bytes.count do |byte|
|
|
99
|
+
(0..8).cover?(byte) || byte == 11 || byte == 12 || (14..31).cover?(byte)
|
|
100
|
+
end
|
|
101
|
+
control_bytes.fdiv(sample.bytesize) > 0.1
|
|
102
|
+
end
|
|
103
|
+
|
|
64
104
|
def run_convert(yaml, options, config)
|
|
65
105
|
opts = build_options(options, config)
|
|
66
106
|
b = backend
|
|
67
|
-
unless
|
|
107
|
+
unless converter_backend?(b)
|
|
68
108
|
handle_error(Yard::Yaml::Error.new("yaml-converter backend not available"), strict: config.strict, context: "backend")
|
|
69
109
|
return empty_result
|
|
70
110
|
end
|
|
71
111
|
|
|
72
112
|
begin
|
|
73
|
-
normalize_result(b
|
|
113
|
+
normalize_result(convert_with_backend(b, yaml, opts))
|
|
74
114
|
rescue StandardError => e
|
|
75
115
|
handle_error(e, strict: config.strict, context: opts[:source_path] || "string")
|
|
76
116
|
empty_result
|
|
77
117
|
end
|
|
78
118
|
end
|
|
79
119
|
|
|
120
|
+
def converter_backend?(backend)
|
|
121
|
+
backend&.respond_to?(:to_markdown) || backend&.respond_to?(:convert)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def convert_with_backend(backend, yaml, options)
|
|
125
|
+
return convert_markdown_backend(backend, yaml, options) if backend.respond_to?(:to_markdown)
|
|
126
|
+
|
|
127
|
+
backend.convert(yaml, options)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def convert_markdown_backend(backend, yaml, options)
|
|
131
|
+
markdown = backend.to_markdown(yaml, options: options)
|
|
132
|
+
metadata = metadata_from_yaml(yaml)
|
|
133
|
+
{
|
|
134
|
+
html: markdown_to_html(markdown),
|
|
135
|
+
title: metadata["title"],
|
|
136
|
+
description: metadata["abstract"],
|
|
137
|
+
meta: metadata,
|
|
138
|
+
}
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def markdown_to_html(markdown)
|
|
142
|
+
require "kramdown"
|
|
143
|
+
require "kramdown-parser-gfm"
|
|
144
|
+
|
|
145
|
+
Kramdown::Document.new(markdown.to_s, input: "GFM").to_html
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def metadata_from_yaml(yaml)
|
|
149
|
+
require "yaml"
|
|
150
|
+
|
|
151
|
+
parsed = YAML.safe_load(yaml.to_s, permitted_classes: [], permitted_symbols: [], aliases: false)
|
|
152
|
+
parsed.is_a?(Hash) ? parsed : {}
|
|
153
|
+
rescue Psych::Exception
|
|
154
|
+
{}
|
|
155
|
+
end
|
|
156
|
+
|
|
80
157
|
def build_options(options, config)
|
|
81
158
|
safe = {
|
|
82
159
|
allow_erb: !!config.allow_erb,
|
data/lib/yard/yaml/emitter.rb
CHANGED
|
@@ -25,13 +25,14 @@ module Yard
|
|
|
25
25
|
# @return [Array<String>] list of written file paths
|
|
26
26
|
def emit!(pages:, output_dir:, config: Yard::Yaml.config)
|
|
27
27
|
pages = Array(pages)
|
|
28
|
+
pages_with_slugs = assign_slugs(pages)
|
|
28
29
|
written = []
|
|
29
30
|
base = File.join(output_dir.to_s, config.out_dir.to_s)
|
|
30
31
|
FileUtils.mkdir_p(base)
|
|
31
32
|
|
|
32
33
|
# Write per-page files
|
|
33
|
-
|
|
34
|
-
slug =
|
|
34
|
+
pages_with_slugs.each do |page|
|
|
35
|
+
slug = page.fetch(:__yard_yaml_slug)
|
|
35
36
|
path = File.join(base, "#{slug}.html")
|
|
36
37
|
html = render_page_html(page)
|
|
37
38
|
atomic_write(path, html, strict: config.strict)
|
|
@@ -41,7 +42,7 @@ module Yard
|
|
|
41
42
|
# Index (optional)
|
|
42
43
|
if config.index
|
|
43
44
|
index_path = File.join(base, "index.html")
|
|
44
|
-
html = render_index_html(
|
|
45
|
+
html = render_index_html(pages_with_slugs)
|
|
45
46
|
atomic_write(index_path, html, strict: config.strict)
|
|
46
47
|
written << index_path
|
|
47
48
|
end
|
|
@@ -58,20 +59,36 @@ module Yard
|
|
|
58
59
|
|
|
59
60
|
private
|
|
60
61
|
|
|
62
|
+
def assign_slugs(pages)
|
|
63
|
+
seen = Hash.new(0)
|
|
64
|
+
pages.map do |page|
|
|
65
|
+
slug = page_slug(page)
|
|
66
|
+
count = seen[slug]
|
|
67
|
+
seen[slug] += 1
|
|
68
|
+
page.merge(__yard_yaml_slug: count.zero? ? slug : "#{slug}-#{count + 1}")
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
61
72
|
def page_slug(page)
|
|
62
73
|
meta = page[:meta] || {}
|
|
63
74
|
slug = meta["slug"] || meta[:slug]
|
|
64
75
|
return sanitize_slug(slug) if slug && !slug.to_s.empty?
|
|
65
76
|
|
|
66
|
-
title = page[:title].to_s
|
|
67
|
-
return sanitize_slug(title) unless title.empty?
|
|
68
|
-
|
|
69
77
|
if page[:path]
|
|
70
|
-
|
|
71
|
-
return
|
|
78
|
+
path_slug = path_slug(page[:path])
|
|
79
|
+
return path_slug unless path_slug.empty?
|
|
72
80
|
end
|
|
73
81
|
|
|
74
|
-
|
|
82
|
+
title = sanitize_slug(page[:title])
|
|
83
|
+
title.empty? ? "page" : title
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def path_slug(path)
|
|
87
|
+
relative = path.to_s.delete_prefix("#{Dir.pwd}/")
|
|
88
|
+
dirname = File.dirname(relative)
|
|
89
|
+
basename = File.basename(relative, File.extname(relative))
|
|
90
|
+
parts = (dirname == ".") ? [basename] : dirname.split(File::SEPARATOR) + [basename]
|
|
91
|
+
sanitize_slug(parts.join("-"))
|
|
75
92
|
end
|
|
76
93
|
|
|
77
94
|
def sanitize_slug(s)
|
|
@@ -108,8 +125,8 @@ module Yard
|
|
|
108
125
|
|
|
109
126
|
def render_index_html(pages)
|
|
110
127
|
rows = pages.map do |p|
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
slug = p[:__yard_yaml_slug] || page_slug(p)
|
|
129
|
+
title = p[:title] || slug
|
|
113
130
|
desc = p[:description]
|
|
114
131
|
%(<li><a href="#{escape_html(slug)}.html">#{escape_html(title)}</a>#{" — #{escape_html(desc)}" if desc}</li>)
|
|
115
132
|
end.join("\n")
|
data/lib/yard/yaml/plugin.rb
CHANGED
|
@@ -4,7 +4,8 @@ module Yard
|
|
|
4
4
|
module Yaml
|
|
5
5
|
# Plugin activation for yard-yaml (Phase 3: config + discovery; still no YARD registrations).
|
|
6
6
|
module Plugin
|
|
7
|
-
|
|
7
|
+
STATE = {activated: false, at_exit_installed: false}
|
|
8
|
+
STATE_MUTEX = Mutex.new
|
|
8
9
|
|
|
9
10
|
class << self
|
|
10
11
|
# Whether the plugin has been activated for the current process.
|
|
@@ -12,7 +13,7 @@ module Yard
|
|
|
12
13
|
#
|
|
13
14
|
# @return [Boolean]
|
|
14
15
|
def activated?
|
|
15
|
-
|
|
16
|
+
STATE[:activated]
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
# Activate the plugin.
|
|
@@ -44,16 +45,82 @@ module Yard
|
|
|
44
45
|
# Non-strict errors are already warned by converter/discovery
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
STATE_MUTEX.synchronize { STATE[:activated] = true }
|
|
48
49
|
nil
|
|
49
50
|
end
|
|
50
51
|
|
|
52
|
+
# Install an at-exit emitter for YARD's plugin loader. YARD loads
|
|
53
|
+
# plugins before it has generated the HTML tree, so converted YAML
|
|
54
|
+
# pages must be written after YARD finishes.
|
|
55
|
+
#
|
|
56
|
+
# @param argv [Array<String>, nil] the YARD argv used to discover output
|
|
57
|
+
# @return [void]
|
|
58
|
+
def install_at_exit(argv = nil)
|
|
59
|
+
should_install = STATE_MUTEX.synchronize do
|
|
60
|
+
if STATE[:at_exit_installed]
|
|
61
|
+
false
|
|
62
|
+
else
|
|
63
|
+
STATE[:at_exit_installed] = true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
return unless should_install
|
|
67
|
+
|
|
68
|
+
at_exit do
|
|
69
|
+
emit!(output_dir: yard_output_dir(argv || ARGV))
|
|
70
|
+
end
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Emit converted pages collected during activation.
|
|
75
|
+
#
|
|
76
|
+
# @param output_dir [String] YARD HTML output directory
|
|
77
|
+
# @return [Array<String>]
|
|
78
|
+
def emit!(output_dir:)
|
|
79
|
+
pages = Yard::Yaml.pages
|
|
80
|
+
return [] if pages.nil? || pages.empty?
|
|
81
|
+
|
|
82
|
+
Yard::Yaml::Emitter.emit!(pages: pages, output_dir: output_dir, config: Yard::Yaml.config)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Resolve YARD's HTML output directory from argv or .yardopts.
|
|
86
|
+
#
|
|
87
|
+
# @param argv [Array<String>]
|
|
88
|
+
# @return [String]
|
|
89
|
+
def yard_output_dir(argv)
|
|
90
|
+
output_dir_from_tokens(Array(argv).map(&:to_s)) ||
|
|
91
|
+
output_dir_from_tokens(yardopts_tokens) ||
|
|
92
|
+
"doc"
|
|
93
|
+
end
|
|
94
|
+
|
|
51
95
|
# Test-helper: reset internal activation flag.
|
|
52
96
|
# Not part of public API; used from test teardown to avoid state leakage.
|
|
53
97
|
def __reset_state__
|
|
54
|
-
|
|
98
|
+
STATE_MUTEX.synchronize do
|
|
99
|
+
STATE[:activated] = false
|
|
100
|
+
STATE[:at_exit_installed] = false
|
|
101
|
+
end
|
|
102
|
+
nil
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def output_dir_from_tokens(tokens)
|
|
108
|
+
tokens.each_with_index do |token, index|
|
|
109
|
+
return tokens[index + 1] if token == "--output" || token == "-o"
|
|
110
|
+
match = token.match(/\A--output=(.+)\z/)
|
|
111
|
+
return match[1] if match
|
|
112
|
+
end
|
|
55
113
|
nil
|
|
56
114
|
end
|
|
115
|
+
|
|
116
|
+
def yardopts_tokens
|
|
117
|
+
return [] unless File.file?(".yardopts")
|
|
118
|
+
|
|
119
|
+
require "shellwords"
|
|
120
|
+
Shellwords.split(File.read(".yardopts"))
|
|
121
|
+
rescue StandardError
|
|
122
|
+
[]
|
|
123
|
+
end
|
|
57
124
|
end
|
|
58
125
|
end
|
|
59
126
|
end
|
|
@@ -19,7 +19,7 @@ module Yard
|
|
|
19
19
|
# @param config [Yard::Yaml::Config]
|
|
20
20
|
# @return [String] HTML fragment (may be empty string)
|
|
21
21
|
def render_for(object, base_dir: Dir.pwd, config: Yard::Yaml.config)
|
|
22
|
-
return "" unless object
|
|
22
|
+
return "" unless object&.respond_to?(:tags)
|
|
23
23
|
|
|
24
24
|
parts = []
|
|
25
25
|
|
data/lib/yard/yaml/tags.rb
CHANGED
|
@@ -24,14 +24,10 @@ module Yard
|
|
|
24
24
|
end
|
|
25
25
|
else
|
|
26
26
|
# Create a minimal shim that records define_tag calls
|
|
27
|
+
calls = []
|
|
27
28
|
lib = Module.new
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def define_tag(*args)
|
|
31
|
-
self.calls ||= []
|
|
32
|
-
self.calls << args
|
|
33
|
-
end
|
|
34
|
-
end
|
|
29
|
+
lib.define_singleton_method(:calls) { calls }
|
|
30
|
+
lib.define_singleton_method(:define_tag) { |*args| calls << args }
|
|
35
31
|
begin
|
|
36
32
|
::YARD::Tags.const_set(:Library, lib)
|
|
37
33
|
rescue StandardError
|
data/lib/yard/yaml/version.rb
CHANGED
data/lib/yard/yaml.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "version_gem"
|
|
3
4
|
require_relative "yaml/version"
|
|
5
|
+
|
|
6
|
+
Yard::Yaml::Version.class_eval do
|
|
7
|
+
extend VersionGem::Basic
|
|
8
|
+
end
|
|
4
9
|
require_relative "yaml/config"
|
|
5
10
|
require_relative "yaml/cli"
|
|
6
11
|
require_relative "yaml/plugin"
|
|
@@ -17,8 +22,11 @@ module Yard
|
|
|
17
22
|
# Generic error for yard-yaml
|
|
18
23
|
class Error < StandardError; end
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
STATE = {
|
|
26
|
+
config: nil,
|
|
27
|
+
pages: nil,
|
|
28
|
+
}
|
|
29
|
+
STATE_MUTEX = Mutex.new
|
|
22
30
|
|
|
23
31
|
class << self
|
|
24
32
|
# Access the global configuration for yard-yaml.
|
|
@@ -28,19 +36,21 @@ module Yard
|
|
|
28
36
|
#
|
|
29
37
|
# @return [Yard::Yaml::Config]
|
|
30
38
|
def config
|
|
31
|
-
|
|
39
|
+
STATE[:config] || STATE_MUTEX.synchronize { STATE[:config] ||= Config.new }
|
|
32
40
|
end
|
|
33
41
|
|
|
34
42
|
# Access collected pages (Phase 3). Nil until plugin activation performs discovery.
|
|
35
43
|
# Each page is a Hash with keys: :path, :html, :title, :description, :meta
|
|
36
44
|
# @return [Array<Hash>, nil]
|
|
37
|
-
|
|
45
|
+
def pages
|
|
46
|
+
STATE[:pages]
|
|
47
|
+
end
|
|
38
48
|
|
|
39
49
|
# Internal: set collected pages (used by Plugin during activation)
|
|
40
50
|
def __set_pages__(list)
|
|
41
|
-
|
|
42
|
-
mirror_pages_to_registry(
|
|
43
|
-
|
|
51
|
+
pages = STATE_MUTEX.synchronize { STATE[:pages] = Array(list) }
|
|
52
|
+
mirror_pages_to_registry(pages)
|
|
53
|
+
pages
|
|
44
54
|
end
|
|
45
55
|
|
|
46
56
|
# Configure the plugin programmatically.
|
|
@@ -80,8 +90,10 @@ module Yard
|
|
|
80
90
|
|
|
81
91
|
# Test-helper: reset memoized config to defaults (not public API)
|
|
82
92
|
def __reset_state__
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
STATE_MUTEX.synchronize do
|
|
94
|
+
STATE[:config] = nil
|
|
95
|
+
STATE[:pages] = nil
|
|
96
|
+
end
|
|
85
97
|
if defined?(::Yard::Yaml::Plugin) && ::Yard::Yaml::Plugin.respond_to?(:__reset_state__)
|
|
86
98
|
::Yard::Yaml::Plugin.__reset_state__
|
|
87
99
|
end
|
data/lib/yard-yaml.rb
CHANGED
data.tar.gz.sig
CHANGED
|
Binary file
|