coradoc 2.0.27 → 2.0.29
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/coradoc/cli.rb +9 -6
- data/lib/coradoc/configurable.rb +6 -3
- data/lib/coradoc/coradoc.rb +5 -2
- data/lib/coradoc/core_model/attribute_reference_resolver.rb +19 -7
- data/lib/coradoc/core_model/base.rb +45 -2
- data/lib/coradoc/core_model/comment_line.rb +1 -1
- data/lib/coradoc/core_model/definition_item.rb +22 -1
- data/lib/coradoc/core_model/horizontal_rule_block.rb +4 -0
- data/lib/coradoc/core_model/include_level_offset.rb +1 -1
- data/lib/coradoc/core_model/include_options.rb +1 -0
- data/lib/coradoc/core_model/inline_content.rb +1 -0
- data/lib/coradoc/core_model/list_block.rb +1 -1
- data/lib/coradoc/core_model/listing_block.rb +4 -0
- data/lib/coradoc/core_model/literal_block.rb +4 -0
- data/lib/coradoc/core_model/pass_block.rb +4 -0
- data/lib/coradoc/core_model/source_block.rb +4 -0
- data/lib/coradoc/core_model/stem_block.rb +4 -0
- data/lib/coradoc/dispatch.rb +1 -0
- data/lib/coradoc/errors.rb +19 -0
- data/lib/coradoc/format_catalog.rb +19 -0
- data/lib/coradoc/format_module.rb +10 -0
- data/lib/coradoc/hooks.rb +1 -1
- data/lib/coradoc/include_selectors/level_offset.rb +0 -2
- data/lib/coradoc/include_selectors/lines.rb +2 -2
- data/lib/coradoc/include_selectors/tags.rb +2 -4
- data/lib/coradoc/introspection/element_counter.rb +2 -2
- data/lib/coradoc/link_rewriter/visitor.rb +5 -14
- data/lib/coradoc/pipeline.rb +64 -5
- data/lib/coradoc/query.rb +8 -8
- data/lib/coradoc/reference/address/anchor.rb +48 -0
- data/lib/coradoc/reference/address/doi.rb +40 -0
- data/lib/coradoc/reference/address/isbn.rb +39 -0
- data/lib/coradoc/reference/address/path.rb +66 -0
- data/lib/coradoc/reference/address/scoped_path.rb +47 -0
- data/lib/coradoc/reference/address/url.rb +41 -0
- data/lib/coradoc/reference/address.rb +153 -0
- data/lib/coradoc/reference/catalog/composite.rb +59 -0
- data/lib/coradoc/reference/catalog/local.rb +97 -0
- data/lib/coradoc/reference/catalog/memory_index.rb +59 -0
- data/lib/coradoc/reference/catalog.rb +33 -0
- data/lib/coradoc/reference/edge/citation_options.rb +16 -0
- data/lib/coradoc/reference/edge/footnote_ref_options.rb +13 -0
- data/lib/coradoc/reference/edge/image_ref_options.rb +15 -0
- data/lib/coradoc/reference/edge/include_options.rb +15 -0
- data/lib/coradoc/reference/edge/kind.rb +72 -0
- data/lib/coradoc/reference/edge/link_options.rb +12 -0
- data/lib/coradoc/reference/edge/navigation_options.rb +12 -0
- data/lib/coradoc/reference/edge/options.rb +13 -0
- data/lib/coradoc/reference/edge.rb +80 -0
- data/lib/coradoc/reference/edge_search.rb +128 -0
- data/lib/coradoc/reference/materializer/base.rb +44 -0
- data/lib/coradoc/reference/materializer/passthrough.rb +31 -0
- data/lib/coradoc/reference/materializer/registry.rb +116 -0
- data/lib/coradoc/reference/materializer.rb +14 -0
- data/lib/coradoc/reference/presentation/base.rb +47 -0
- data/lib/coradoc/reference/presentation/custom_hierarchy.rb +104 -0
- data/lib/coradoc/reference/presentation/page.rb +20 -0
- data/lib/coradoc/reference/presentation/single_document.rb +35 -0
- data/lib/coradoc/reference/presentation/split_pages.rb +118 -0
- data/lib/coradoc/reference/presentation.rb +16 -0
- data/lib/coradoc/reference/resolution.rb +184 -0
- data/lib/coradoc/reference/resolver/base.rb +15 -0
- data/lib/coradoc/reference/resolver/caching.rb +37 -0
- data/lib/coradoc/reference/resolver/catalog.rb +69 -0
- data/lib/coradoc/reference/resolver/chain.rb +33 -0
- data/lib/coradoc/reference/resolver.rb +20 -0
- data/lib/coradoc/reference/result/ambiguous.rb +23 -0
- data/lib/coradoc/reference/result/base.rb +46 -0
- data/lib/coradoc/reference/result/missing.rb +14 -0
- data/lib/coradoc/reference/result/resolved.rb +22 -0
- data/lib/coradoc/reference/result.rb +20 -0
- data/lib/coradoc/reference.rb +65 -0
- data/lib/coradoc/registry.rb +6 -6
- data/lib/coradoc/resolve_includes.rb +2 -2
- data/lib/coradoc/validation.rb +44 -4
- data/lib/coradoc/version.rb +1 -1
- data/lib/coradoc.rb +1 -1
- metadata +45 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'lutaml/model'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
module Reference
|
|
7
|
+
module Result
|
|
8
|
+
# Base class for resolution outcomes. Subclasses are value types.
|
|
9
|
+
# Every Result carries the Edge that asked — so callers can log,
|
|
10
|
+
# trace, and re-route without re-resolving.
|
|
11
|
+
class Base < Lutaml::Model::Serializable
|
|
12
|
+
attribute :edge, Coradoc::Reference::Edge
|
|
13
|
+
attribute :address, Coradoc::Reference::Address
|
|
14
|
+
|
|
15
|
+
def resolved?
|
|
16
|
+
is_a?(Result::Resolved)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def ambiguous?
|
|
20
|
+
is_a?(Result::Ambiguous)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def missing?
|
|
24
|
+
is_a?(Result::Missing)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# This Result as seen by +edge+. Returns self when the edge is
|
|
28
|
+
# value-equal to the one embedded; otherwise rebuilds the same
|
|
29
|
+
# outcome (target/candidates preserved) for the asking edge.
|
|
30
|
+
# Used by caching resolvers so two edges sharing an Address
|
|
31
|
+
# never see each other's identity.
|
|
32
|
+
def for_edge(edge)
|
|
33
|
+
return self if self.edge == edge
|
|
34
|
+
|
|
35
|
+
self.class.build(edge: edge, address: address, **result_data)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def result_data
|
|
41
|
+
{}
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Reference
|
|
5
|
+
module Result
|
|
6
|
+
# No catalog knows this address. Caller's +missing:+ policy decides.
|
|
7
|
+
class Missing < Base
|
|
8
|
+
def self.build(edge:, address:)
|
|
9
|
+
new(edge: edge, address: address)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Reference
|
|
5
|
+
module Result
|
|
6
|
+
# Catalog knew the address; exactly one Content was returned.
|
|
7
|
+
class Resolved < Base
|
|
8
|
+
attribute :target, Coradoc::CoreModel::Base
|
|
9
|
+
|
|
10
|
+
def self.build(edge:, address:, target:)
|
|
11
|
+
new(edge: edge, address: address, target: target)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def result_data
|
|
17
|
+
{ target: target }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Coradoc
|
|
4
|
+
module Reference
|
|
5
|
+
# Sum type for resolution outcomes. Callers pattern-match on the
|
|
6
|
+
# concrete subclass — never check +nil+.
|
|
7
|
+
#
|
|
8
|
+
# case resolver.resolve(edge)
|
|
9
|
+
# in Result::Resolved => r # have the target
|
|
10
|
+
# in Result::Ambiguous => a # multiple candidates
|
|
11
|
+
# in Result::Missing => m # catalog does not know
|
|
12
|
+
# end
|
|
13
|
+
module Result
|
|
14
|
+
autoload :Base, "#{__dir__}/result/base"
|
|
15
|
+
autoload :Resolved, "#{__dir__}/result/resolved"
|
|
16
|
+
autoload :Ambiguous, "#{__dir__}/result/ambiguous"
|
|
17
|
+
autoload :Missing, "#{__dir__}/result/missing"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'coradoc/errors'
|
|
4
|
+
|
|
5
|
+
module Coradoc
|
|
6
|
+
# Unified content-graph reference resolution.
|
|
7
|
+
#
|
|
8
|
+
# Every referenceable thing in a document is a Content node; every
|
|
9
|
+
# reference is a directed Edge with a kind. The four primitives:
|
|
10
|
+
#
|
|
11
|
+
# Content — CoreModel::Base with an id (already on Base).
|
|
12
|
+
# Document — Content that contains Content (composite).
|
|
13
|
+
# Reference::Edge — directed {source Content, target Address, kind}.
|
|
14
|
+
# Reference::Address — scheme-aware locator (anchor, path, url, ...).
|
|
15
|
+
#
|
|
16
|
+
# Same Content graph → N Presentations → M Materializers. The public
|
|
17
|
+
# entry point is +Coradoc.resolve_references+.
|
|
18
|
+
module Reference
|
|
19
|
+
# Base class for reference-resolution errors. All subclasses inherit
|
|
20
|
+
# from here so callers can rescue the family with one +rescue+ clause.
|
|
21
|
+
class Error < Coradoc::Error; end
|
|
22
|
+
|
|
23
|
+
# Raised when no catalog knew the requested Address and the
|
|
24
|
+
# +missing:+ policy is :error.
|
|
25
|
+
class MissingReferenceError < Error
|
|
26
|
+
attr_reader :address
|
|
27
|
+
|
|
28
|
+
def initialize(message = nil, address: nil)
|
|
29
|
+
@address = address
|
|
30
|
+
super(message || "Reference not found: #{address}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Raised when multiple catalogs matched an Address and the
|
|
35
|
+
# +ambiguous:+ policy is :error.
|
|
36
|
+
class AmbiguousReferenceError < Error
|
|
37
|
+
attr_reader :address, :candidates
|
|
38
|
+
|
|
39
|
+
def initialize(message = nil, address: nil, candidates: nil)
|
|
40
|
+
@address = address
|
|
41
|
+
@candidates = candidates
|
|
42
|
+
super(message || "Reference is ambiguous: #{address}")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Raised when the catalog index is malformed — a programmer
|
|
47
|
+
# error, not a runtime condition. Surfaces as a clear message
|
|
48
|
+
# rather than a vague NoMethodError.
|
|
49
|
+
class InvalidCatalogError < Error; end
|
|
50
|
+
|
|
51
|
+
# Raised when building an Edge whose kind was never registered.
|
|
52
|
+
# External kinds register via +Edge.register_kind+ (OCP).
|
|
53
|
+
class UnknownKindError < Error; end
|
|
54
|
+
|
|
55
|
+
autoload :Address, "#{__dir__}/reference/address"
|
|
56
|
+
autoload :Edge, "#{__dir__}/reference/edge"
|
|
57
|
+
autoload :Catalog, "#{__dir__}/reference/catalog"
|
|
58
|
+
autoload :Result, "#{__dir__}/reference/result"
|
|
59
|
+
autoload :Resolver, "#{__dir__}/reference/resolver"
|
|
60
|
+
autoload :Presentation, "#{__dir__}/reference/presentation"
|
|
61
|
+
autoload :Materializer, "#{__dir__}/reference/materializer"
|
|
62
|
+
autoload :EdgeSearch, "#{__dir__}/reference/edge_search"
|
|
63
|
+
autoload :Resolution, "#{__dir__}/reference/resolution"
|
|
64
|
+
end
|
|
65
|
+
end
|
data/lib/coradoc/registry.rb
CHANGED
|
@@ -102,24 +102,24 @@ module Coradoc
|
|
|
102
102
|
#
|
|
103
103
|
# @yield [Symbol, Object] name and item
|
|
104
104
|
# @return [Enumerator]
|
|
105
|
-
def each(&
|
|
106
|
-
@items.each(&
|
|
105
|
+
def each(&)
|
|
106
|
+
@items.each(&)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
# Iterate over item values
|
|
110
110
|
#
|
|
111
111
|
# @yield [Object]
|
|
112
112
|
# @return [Enumerator]
|
|
113
|
-
def each_value(&
|
|
114
|
-
@items.each_value(&
|
|
113
|
+
def each_value(&)
|
|
114
|
+
@items.each_value(&)
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
# Iterate over item names
|
|
118
118
|
#
|
|
119
119
|
# @yield [Symbol]
|
|
120
120
|
# @return [Enumerator]
|
|
121
|
-
def each_key(&
|
|
122
|
-
@items.each_key(&
|
|
121
|
+
def each_key(&)
|
|
122
|
+
@items.each_key(&)
|
|
123
123
|
end
|
|
124
124
|
|
|
125
125
|
# Find an item whose processor_match? returns true for the given filename
|
|
@@ -24,8 +24,8 @@ module Coradoc
|
|
|
24
24
|
DEFAULT_MAX_DEPTH = 64
|
|
25
25
|
|
|
26
26
|
class << self
|
|
27
|
-
def call(core, resolver:, base_dir:, **
|
|
28
|
-
new(resolver: resolver, base_dir: base_dir, **
|
|
27
|
+
def call(core, resolver:, base_dir:, **)
|
|
28
|
+
new(resolver: resolver, base_dir: base_dir, **).call(core)
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
data/lib/coradoc/validation.rb
CHANGED
|
@@ -28,6 +28,46 @@ module Coradoc
|
|
|
28
28
|
# end
|
|
29
29
|
#
|
|
30
30
|
module Validation
|
|
31
|
+
module_function
|
|
32
|
+
|
|
33
|
+
# Targets of every unresolved +include::+ edge in the tree
|
|
34
|
+
# (deduplicated, in document order). A document is "unresolved"
|
|
35
|
+
# when it was parsed in graph mode and never went through
|
|
36
|
+
# +Coradoc.resolve_includes+.
|
|
37
|
+
def unresolved_include_targets(model)
|
|
38
|
+
targets = []
|
|
39
|
+
walk_nodes(model) do |node|
|
|
40
|
+
targets << node.target if node.is_a?(Coradoc::CoreModel::Include)
|
|
41
|
+
end
|
|
42
|
+
targets.uniq
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Serialization boundary check: formats that cannot represent an
|
|
46
|
+
# unresolved include edge (FormatModule::Interface
|
|
47
|
+
# #preserves_unresolved_includes? == false) must not silently drop
|
|
48
|
+
# the content — raise UnresolvedIncludesError instead, pointing at
|
|
49
|
+
# the hydration step (resolve_includes).
|
|
50
|
+
def guard_unresolved_includes!(model, format_module)
|
|
51
|
+
return if format_module.preserves_unresolved_includes?
|
|
52
|
+
|
|
53
|
+
targets = unresolved_include_targets(model)
|
|
54
|
+
return if targets.empty?
|
|
55
|
+
|
|
56
|
+
raise Coradoc::UnresolvedIncludesError, targets
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def walk_nodes(node, &block)
|
|
60
|
+
return unless node.is_a?(Coradoc::CoreModel::Base)
|
|
61
|
+
|
|
62
|
+
yield node
|
|
63
|
+
return unless node.is_a?(Coradoc::CoreModel::HasChildren)
|
|
64
|
+
|
|
65
|
+
children = node.children
|
|
66
|
+
return unless children
|
|
67
|
+
|
|
68
|
+
children.each { |child| walk_nodes(child, &block) }
|
|
69
|
+
end
|
|
70
|
+
|
|
31
71
|
# A single validation error
|
|
32
72
|
class Error
|
|
33
73
|
attr_reader :path, :message, :code, :element
|
|
@@ -600,8 +640,8 @@ module Coradoc
|
|
|
600
640
|
#
|
|
601
641
|
# @yield Schema definition block
|
|
602
642
|
# @return [Schema] The defined schema
|
|
603
|
-
def define(&
|
|
604
|
-
Schema.define(&
|
|
643
|
+
def define(&)
|
|
644
|
+
Schema.define(&)
|
|
605
645
|
end
|
|
606
646
|
|
|
607
647
|
# Generate a validation schema from a CoreModel class
|
|
@@ -614,8 +654,8 @@ module Coradoc
|
|
|
614
654
|
# schema = Coradoc::Validation.auto_schema(Coradoc::CoreModel::Block)
|
|
615
655
|
# result = schema.validate(document)
|
|
616
656
|
#
|
|
617
|
-
def auto_schema(model_class, **
|
|
618
|
-
SchemaGenerator.generate(model_class, **
|
|
657
|
+
def auto_schema(model_class, **)
|
|
658
|
+
SchemaGenerator.generate(model_class, **)
|
|
619
659
|
end
|
|
620
660
|
|
|
621
661
|
# Validate a document with default schema
|
data/lib/coradoc/version.rb
CHANGED
data/lib/coradoc.rb
CHANGED
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
# Coradoc.serialize(doc, to: :html)
|
|
31
31
|
|
|
32
32
|
require_relative 'coradoc/coradoc'
|
|
33
|
-
require_relative 'coradoc/version'
|
|
34
33
|
|
|
35
34
|
module Coradoc
|
|
35
|
+
autoload :VERSION, 'coradoc/version'
|
|
36
36
|
autoload :CLI, 'coradoc/cli'
|
|
37
37
|
autoload :Visitor, 'coradoc/visitor'
|
|
38
38
|
autoload :LinkRewriter, 'coradoc/link_rewriter'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: coradoc
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.29
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose Inc.
|
|
@@ -131,6 +131,49 @@ files:
|
|
|
131
131
|
- lib/coradoc/performance_regression.rb
|
|
132
132
|
- lib/coradoc/pipeline.rb
|
|
133
133
|
- lib/coradoc/query.rb
|
|
134
|
+
- lib/coradoc/reference.rb
|
|
135
|
+
- lib/coradoc/reference/address.rb
|
|
136
|
+
- lib/coradoc/reference/address/anchor.rb
|
|
137
|
+
- lib/coradoc/reference/address/doi.rb
|
|
138
|
+
- lib/coradoc/reference/address/isbn.rb
|
|
139
|
+
- lib/coradoc/reference/address/path.rb
|
|
140
|
+
- lib/coradoc/reference/address/scoped_path.rb
|
|
141
|
+
- lib/coradoc/reference/address/url.rb
|
|
142
|
+
- lib/coradoc/reference/catalog.rb
|
|
143
|
+
- lib/coradoc/reference/catalog/composite.rb
|
|
144
|
+
- lib/coradoc/reference/catalog/local.rb
|
|
145
|
+
- lib/coradoc/reference/catalog/memory_index.rb
|
|
146
|
+
- lib/coradoc/reference/edge.rb
|
|
147
|
+
- lib/coradoc/reference/edge/citation_options.rb
|
|
148
|
+
- lib/coradoc/reference/edge/footnote_ref_options.rb
|
|
149
|
+
- lib/coradoc/reference/edge/image_ref_options.rb
|
|
150
|
+
- lib/coradoc/reference/edge/include_options.rb
|
|
151
|
+
- lib/coradoc/reference/edge/kind.rb
|
|
152
|
+
- lib/coradoc/reference/edge/link_options.rb
|
|
153
|
+
- lib/coradoc/reference/edge/navigation_options.rb
|
|
154
|
+
- lib/coradoc/reference/edge/options.rb
|
|
155
|
+
- lib/coradoc/reference/edge_search.rb
|
|
156
|
+
- lib/coradoc/reference/materializer.rb
|
|
157
|
+
- lib/coradoc/reference/materializer/base.rb
|
|
158
|
+
- lib/coradoc/reference/materializer/passthrough.rb
|
|
159
|
+
- lib/coradoc/reference/materializer/registry.rb
|
|
160
|
+
- lib/coradoc/reference/presentation.rb
|
|
161
|
+
- lib/coradoc/reference/presentation/base.rb
|
|
162
|
+
- lib/coradoc/reference/presentation/custom_hierarchy.rb
|
|
163
|
+
- lib/coradoc/reference/presentation/page.rb
|
|
164
|
+
- lib/coradoc/reference/presentation/single_document.rb
|
|
165
|
+
- lib/coradoc/reference/presentation/split_pages.rb
|
|
166
|
+
- lib/coradoc/reference/resolution.rb
|
|
167
|
+
- lib/coradoc/reference/resolver.rb
|
|
168
|
+
- lib/coradoc/reference/resolver/base.rb
|
|
169
|
+
- lib/coradoc/reference/resolver/caching.rb
|
|
170
|
+
- lib/coradoc/reference/resolver/catalog.rb
|
|
171
|
+
- lib/coradoc/reference/resolver/chain.rb
|
|
172
|
+
- lib/coradoc/reference/result.rb
|
|
173
|
+
- lib/coradoc/reference/result/ambiguous.rb
|
|
174
|
+
- lib/coradoc/reference/result/base.rb
|
|
175
|
+
- lib/coradoc/reference/result/missing.rb
|
|
176
|
+
- lib/coradoc/reference/result/resolved.rb
|
|
134
177
|
- lib/coradoc/registry.rb
|
|
135
178
|
- lib/coradoc/relative_path.rb
|
|
136
179
|
- lib/coradoc/resolve_includes.rb
|
|
@@ -144,6 +187,7 @@ metadata:
|
|
|
144
187
|
homepage_uri: https://github.com/lutaml/coradoc
|
|
145
188
|
source_code_uri: https://github.com/lutaml/coradoc
|
|
146
189
|
changelog_uri: https://github.com/lutaml/coradoc/blob/main/CHANGELOG.md
|
|
190
|
+
rubygems_mfa_required: 'true'
|
|
147
191
|
rdoc_options: []
|
|
148
192
|
require_paths:
|
|
149
193
|
- lib
|