glossarist 2.13.9 → 2.13.10
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/PROMPT-NOW.md +227 -0
- data/lib/glossarist/figure.rb +1 -1
- data/lib/glossarist/formula.rb +1 -1
- data/lib/glossarist/mention_parser.rb +174 -0
- data/lib/glossarist/{non_verbal_entity.rb → non_concept_entity.rb} +17 -8
- data/lib/glossarist/non_verb_rep.rb +14 -5
- data/lib/glossarist/reference_extractor.rb +59 -4
- data/lib/glossarist/{shared_non_verbal_entity.rb → shared_non_concept_entity.rb} +6 -3
- data/lib/glossarist/table.rb +1 -1
- data/lib/glossarist/validators/no_raw_html.rb +86 -0
- data/lib/glossarist/validators.rb +10 -0
- data/lib/glossarist/version.rb +1 -1
- data/lib/glossarist.rb +29 -2
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 16c44282632761dbbfeb3b63ff619b519648f0af7306ee5aa85fba1606244bd6
|
|
4
|
+
data.tar.gz: 37e8af5033c014195228ba11f50528b7aca8c06424533196ea0c318d5f78c7f0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8dadb718f3a39e49167eb1d8aa8eeada22f826c049be68dcfe151cd0980edb0e80006a51b21f64912dcc9e9d4ef21ff47618002b6d7d1496b88669cb39932620
|
|
7
|
+
data.tar.gz: 29f66da8f1f743c7f5424e966bf4b19a94e83264146d9c3156243f0f0a39e728874fcc4cbf6f2a2d8c77bd4799406083162d27b5f675dd1fe0aa88246091222d
|
data/PROMPT-NOW.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# PROMPT-NOW: parseMention extension + legacy <<>> deprecation + terminology alignment + raw-HTML validation
|
|
2
|
+
|
|
3
|
+
> **Context:** concept-browser is implementing a strict DATA/DEPLOYMENT boundary for inline content. This requires all Glossarist libraries (JS, Ruby, and the concept-model schema) to parse the same unified `{{kind:target}}` syntax and align terminology. The JS library changes are tracked in a parallel PROMPT-NOW.md; this prompt mirrors them for the Ruby library. Self-contained.
|
|
4
|
+
|
|
5
|
+
## Background: the principle
|
|
6
|
+
|
|
7
|
+
**Dataset authors** write `{{kind:target}}` mentions in concept text. They don't know where their dataset will be deployed.
|
|
8
|
+
|
|
9
|
+
**Concept-browser** resolves every mention at runtime via `ReferenceResolver`. For this to work, `parse_mention` must produce a canonical `{kind, target, label}` shape for every mention kind — identical to the JS library's output.
|
|
10
|
+
|
|
11
|
+
The current parser recognizes `cite:`, `urn:`, `fig:`/`figure:`, `table:`/`tbl:`, `formula:`/`eq:`, and bare designation/numeric. Three new kinds are needed: `link`, `image`, `bib`.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## P1: parse_mention extension — `link`, `image`, `bib` kinds
|
|
16
|
+
|
|
17
|
+
### New kinds to parse
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
Glossarist.parse_mention("{{link:https://example.com/page}}")
|
|
21
|
+
# => { kind: 'link-ref', uri: 'https://example.com/page', label: nil }
|
|
22
|
+
|
|
23
|
+
Glossarist.parse_mention("{{link:https://example.com, click here}}")
|
|
24
|
+
# => { kind: 'link-ref', uri: 'https://example.com', label: 'click here' }
|
|
25
|
+
|
|
26
|
+
Glossarist.parse_mention("{{image:diagram.png}}")
|
|
27
|
+
# => { kind: 'image-ref', src: 'diagram.png', alt: nil }
|
|
28
|
+
|
|
29
|
+
Glossarist.parse_mention("{{image:diagram.png, The diagram}}")
|
|
30
|
+
# => { kind: 'image-ref', src: 'diagram.png', alt: 'The diagram' }
|
|
31
|
+
|
|
32
|
+
Glossarist.parse_mention("{{bib:ref_1}}")
|
|
33
|
+
# => { kind: 'bib-ref', id: 'ref_1', label: nil }
|
|
34
|
+
|
|
35
|
+
Glossarist.parse_mention("{{bib:ref_1, ISO 704}}")
|
|
36
|
+
# => { kind: 'bib-ref', id: 'ref_1', label: 'ISO 704' }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Design notes
|
|
40
|
+
|
|
41
|
+
- `link` uses `uri` (not `id`) because the target is a URL, not a dataset-local handle. The URL is canonical — external to all datasets, deployment-independent.
|
|
42
|
+
- `image` uses `src` (not `uri`) and `alt` (not `label`) because it's an embed, not a link. The `alt` field is the accessibility text.
|
|
43
|
+
- `bib` uses `id` because it references a dataset-local bibliography entry. This is the case-3-only path — the author explicitly wants a flat bibliographic record, not a concept resolution.
|
|
44
|
+
|
|
45
|
+
The parsed shapes MUST match the JS library's output exactly (same keys, same values) so concept-browser can consume either library's output interchangeably.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## P2: Legacy `<<target, caption>>` deprecation
|
|
50
|
+
|
|
51
|
+
### The problem
|
|
52
|
+
|
|
53
|
+
The AsciiDoc xref syntax `<<target, caption>>` has been overloaded for:
|
|
54
|
+
1. **Non-concept entity xrefs** (legitimate AsciiDoc use — should map to `{{fig/table/formula:target, caption}}`)
|
|
55
|
+
2. **Bibliography lookups** (wrong — bypasses the resolution cascade)
|
|
56
|
+
3. **Concept citations** (wrong — should use `{{cite:target, caption}}`)
|
|
57
|
+
|
|
58
|
+
### Proposed change
|
|
59
|
+
|
|
60
|
+
When the parser encounters `<<target, caption>>`:
|
|
61
|
+
|
|
62
|
+
1. **Emit a deprecation warning** via Ruby's `Warning` module:
|
|
63
|
+
|
|
64
|
+
```ruby
|
|
65
|
+
Warning.warn("[glossarist] <<#{target}, #{caption}>> is deprecated. " \
|
|
66
|
+
"Use {{fig/table/formula:#{target}, #{caption}}} for non-concept entities, " \
|
|
67
|
+
"or {{cite:#{target}, #{caption}}} for concept citations.")
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
2. **Re-parse** based on what `target` resolves to:
|
|
71
|
+
- If `target` matches a figure/table/formula entity in the dataset → treat as `{{kind:target, caption}}`
|
|
72
|
+
- Otherwise → treat as `{{cite:target, caption}}` (let concept-browser's resolution cascade handle it)
|
|
73
|
+
|
|
74
|
+
3. **Do NOT** treat as a bibliography lookup. Bibliography is reached only via `{{bib:id}}` (explicit) or via the resolution cascade's case-3 fallback (implicit).
|
|
75
|
+
|
|
76
|
+
### RuboCop cop (optional)
|
|
77
|
+
|
|
78
|
+
Consider a custom RuboCop cop that flags `<<...,...>>` in concept text fixtures:
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
# .rubocop.yml
|
|
82
|
+
require: glossarist/rubocop
|
|
83
|
+
|
|
84
|
+
Glossarist/NoLegacyXrefSyntax:
|
|
85
|
+
Enabled: true
|
|
86
|
+
Description: 'Use {{kind:target}} instead of <<target, caption>>'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## P3: Terminology alignment
|
|
92
|
+
|
|
93
|
+
### The rename
|
|
94
|
+
|
|
95
|
+
Rename `NonVerbalEntity` → `NonConceptEntity` in Ruby model classes (where referring to Figure/Table/Formula). The terminology fix:
|
|
96
|
+
|
|
97
|
+
- **Non-verbal** refers to the modality of expression (non-verbal designation: symbol, formula expression). Properties OF concepts.
|
|
98
|
+
- **Non-concept** refers to entities that are NOT concepts at all (Figure, Table, Formula). Standalone dataset entities.
|
|
99
|
+
|
|
100
|
+
### Proposed change
|
|
101
|
+
|
|
102
|
+
```ruby
|
|
103
|
+
# BEFORE
|
|
104
|
+
module Glossarist
|
|
105
|
+
class NonVerbalEntity < GlossaristModel; end # ambiguous
|
|
106
|
+
class SharedNonVerbalEntity < NonVerbalEntity; end
|
|
107
|
+
class NonVerbRep < GlossaristModel; end # concept-local designation
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# AFTER
|
|
111
|
+
module Glossarist
|
|
112
|
+
class NonConceptEntity < GlossaristModel; end # clear — NOT a concept
|
|
113
|
+
class NonVerbRep < GlossaristModel; end # unchanged — IS a designation
|
|
114
|
+
|
|
115
|
+
# Deprecated alias for backward compat
|
|
116
|
+
# @deprecated Use NonConceptEntity instead.
|
|
117
|
+
NonVerbalEntity = NonConceptEntity
|
|
118
|
+
SharedNonVerbalEntity = NonConceptEntity
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Keep `NonVerbRep` unchanged — it IS a non-verbal representation (a designation of a concept).
|
|
123
|
+
|
|
124
|
+
Provide deprecated aliases for one release cycle.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## P4: Raw-HTML validation
|
|
129
|
+
|
|
130
|
+
### The problem
|
|
131
|
+
|
|
132
|
+
Concept text sometimes contains raw HTML instead of typed mention syntax:
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
# BAD — raw HTML in YAML
|
|
136
|
+
definition:
|
|
137
|
+
- content: See <a href="http://std.iec.ch/...">IEV</a> for details.
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
This bypasses the renderer, is brittle, has no accessibility contract, and can embed deployment-specific URLs.
|
|
141
|
+
|
|
142
|
+
### Proposed change
|
|
143
|
+
|
|
144
|
+
Add a validator:
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
module Glossarist
|
|
148
|
+
module Validators
|
|
149
|
+
class NoRawHtml
|
|
150
|
+
def self.call(text)
|
|
151
|
+
issues = []
|
|
152
|
+
|
|
153
|
+
# <a href="URL">label</a> → {{link:URL, label}}
|
|
154
|
+
text.scan(/<a\s+href="([^"]+)"[^>]*>([^<]*)<\/a>/i) do |url, label|
|
|
155
|
+
issues << {
|
|
156
|
+
severity: 'warning',
|
|
157
|
+
match: "<a href=\"#{url}\">#{label}</a>",
|
|
158
|
+
suggestion: label && !label.empty? ? "{{link:#{url}, #{label}}}" : "{{link:#{url}}}",
|
|
159
|
+
message: 'Use {{link:}} instead of raw <a> tags',
|
|
160
|
+
}
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# <img src="SRC" alt="ALT"> → {{image:SRC, ALT}}
|
|
164
|
+
text.scan(/<img\s+src="([^"]+)"(?:\s+alt="([^"]*)")?[^>]*>/i) do |src, alt|
|
|
165
|
+
suggestion = alt ? "{{image:#{src}, #{alt}}}" : "{{image:#{src}}}"
|
|
166
|
+
issues << {
|
|
167
|
+
severity: 'warning',
|
|
168
|
+
match: "<img src=\"#{src}\"#{" alt=\"#{alt}\"" if alt}>",
|
|
169
|
+
suggestion: suggestion,
|
|
170
|
+
message: 'Use {{image:}} instead of raw <img> tags',
|
|
171
|
+
}
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
issues
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Replacement suggestions:
|
|
182
|
+
|
|
183
|
+
| Raw HTML | Suggested replacement |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `<a href="URL">label</a>` | `{{link:URL, label}}` |
|
|
186
|
+
| `<a href="URL">URL</a>` | `{{link:URL}}` |
|
|
187
|
+
| `<img src="SRC">` | `{{image:SRC}}` |
|
|
188
|
+
| `<img src="SRC" alt="ALT">` | `{{image:SRC, ALT}}` |
|
|
189
|
+
| `<iframe src="URL">` | `{{link:URL}}` (iframes not supported as embeds) |
|
|
190
|
+
|
|
191
|
+
The validator is opt-in — concept-browser (or the data pipeline) can call it during data loading to warn dataset authors.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## Summary
|
|
196
|
+
|
|
197
|
+
| Change | Impact |
|
|
198
|
+
|---|---|
|
|
199
|
+
| P1: parse_mention extension | New parsed shapes for `link`, `image`, `bib` (must match JS output exactly) |
|
|
200
|
+
| P2: Legacy `<<>>` deprecation | Warning + re-parse; optional RuboCop cop |
|
|
201
|
+
| P3: Terminology rename | `NonVerbalEntity` → `NonConceptEntity` (with deprecated alias) |
|
|
202
|
+
| P4: Raw-HTML validator | New `Glossarist::Validators::NoRawHtml` class |
|
|
203
|
+
|
|
204
|
+
## Coordination
|
|
205
|
+
|
|
206
|
+
- **concept-model** needs schema changes for the new kinds and terminology (parallel PROMPT-NOW.md).
|
|
207
|
+
- **glossarist-js** needs the same parser extension (parallel PROMPT-NOW.md).
|
|
208
|
+
- **concept-browser** wires the resolvers once both libraries ship the new parse output.
|
|
209
|
+
- A **shared contract test fixture** (a concept with every kind of mention) should be consumed by all implementations to prevent syntax drift. The fixture lives in concept-model; both libraries import it.
|
|
210
|
+
|
|
211
|
+
## Cross-library contract
|
|
212
|
+
|
|
213
|
+
The parsed output from `parse_mention` MUST be identical between the Ruby and JS libraries:
|
|
214
|
+
|
|
215
|
+
```ruby
|
|
216
|
+
# Ruby
|
|
217
|
+
Glossarist.parse_mention("{{link:https://example.com, click here}}")
|
|
218
|
+
# => { kind: 'link-ref', uri: 'https://example.com', label: 'click here' }
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
```ts
|
|
222
|
+
// JS
|
|
223
|
+
parseMention("{{link:https://example.com, click here}}")
|
|
224
|
+
// => { kind: 'link-ref', uri: 'https://example.com', label: 'click here' }
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Same keys. Same values. Same symbol-as-string for `kind`. This allows concept-browser to consume either library's output without translation.
|
data/lib/glossarist/figure.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Glossarist
|
|
|
13
13
|
# subfigures.
|
|
14
14
|
#
|
|
15
15
|
# Caption, description, and alt are localized (hash keyed by ISO 639 code).
|
|
16
|
-
class Figure <
|
|
16
|
+
class Figure < SharedNonConceptEntity
|
|
17
17
|
attribute :images, FigureImage, collection: true
|
|
18
18
|
attribute :subfigures, Figure, collection: true
|
|
19
19
|
|
data/lib/glossarist/formula.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Glossarist
|
|
|
7
7
|
# shared across concepts. The mathematical expression is stored in a
|
|
8
8
|
# notation format (LaTeX, MathML, AsciiMath). Caption, description, and
|
|
9
9
|
# alt are localized for accessibility.
|
|
10
|
-
class Formula <
|
|
10
|
+
class Formula < SharedNonConceptEntity
|
|
11
11
|
attribute :expression, :hash
|
|
12
12
|
attribute :notation, :string
|
|
13
13
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Glossarist
|
|
4
|
+
# Reference kinds produced by parse_mention for the unified
|
|
5
|
+
# {{kind:target}} / {{kind:target, label}} mention syntax.
|
|
6
|
+
#
|
|
7
|
+
# The shape produced for each kind is the cross-library contract —
|
|
8
|
+
# glossarist-js produces the same keys, same values, so concept-browser
|
|
9
|
+
# can consume either library's output interchangeably without translation.
|
|
10
|
+
module MentionKinds
|
|
11
|
+
# {{link:URL}} or {{link:URL, label}} — external URL link.
|
|
12
|
+
# `uri` is canonical (deployment-independent); `label` is the display
|
|
13
|
+
# text (nil means render the URL itself).
|
|
14
|
+
LINK_REF = "link-ref"
|
|
15
|
+
|
|
16
|
+
# {{image:src}} or {{image:src, alt}} — embedded image.
|
|
17
|
+
# `src` is the image source; `alt` is accessibility text (nil means
|
|
18
|
+
# no a11y label). Distinct from link-ref because it's an embed, not
|
|
19
|
+
# a navigation link.
|
|
20
|
+
IMAGE_REF = "image-ref"
|
|
21
|
+
|
|
22
|
+
# {{bib:id}} or {{bib:id, label}} — dataset-local bibliography entry.
|
|
23
|
+
# `id` references an entry in the dataset's bibliography.yaml. This is
|
|
24
|
+
# the case-3-only path — the author explicitly wants a flat
|
|
25
|
+
# bibliographic record, not a concept resolution.
|
|
26
|
+
BIB_REF = "bib-ref"
|
|
27
|
+
|
|
28
|
+
# {{cite:id}} or {{cite:id, label}} — concept citation.
|
|
29
|
+
CITE_REF = "cite-ref"
|
|
30
|
+
|
|
31
|
+
# {{fig:id}} / {{figure:id}} — non-concept figure entity xref.
|
|
32
|
+
FIG_REF = "fig-ref"
|
|
33
|
+
|
|
34
|
+
# {{table:id}} / {{tbl:id}} — non-concept table entity xref.
|
|
35
|
+
TABLE_REF = "table-ref"
|
|
36
|
+
|
|
37
|
+
# {{formula:id}} / {{eq:id}} — non-concept formula entity xref.
|
|
38
|
+
FORMULA_REF = "formula-ref"
|
|
39
|
+
|
|
40
|
+
# {{123}} or {{123, label}} — local concept by numeric id.
|
|
41
|
+
LOCAL_CONCEPT_REF = "local-concept-ref"
|
|
42
|
+
|
|
43
|
+
# {{designation}} — concept by designation text.
|
|
44
|
+
DESIGNATION_REF = "designation-ref"
|
|
45
|
+
|
|
46
|
+
# {{urn:...}} — URN reference.
|
|
47
|
+
URN_REF = "urn-ref"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Parsed mention result — a plain Hash with symbol keys. Built by
|
|
51
|
+
# Glossarist.parse_mention. The shape per kind is documented on
|
|
52
|
+
# MentionKinds constants above.
|
|
53
|
+
#
|
|
54
|
+
# Examples:
|
|
55
|
+
#
|
|
56
|
+
# Glossarist.parse_mention("{{link:https://example.com, click here}}")
|
|
57
|
+
# # => { kind: "link-ref", uri: "https://example.com", label: "click here" }
|
|
58
|
+
#
|
|
59
|
+
# Glossarist.parse_mention("{{image:diagram.png, The diagram}}")
|
|
60
|
+
# # => { kind: "image-ref", src: "diagram.png", alt: "The diagram" }
|
|
61
|
+
#
|
|
62
|
+
# Glossarist.parse_mention("{{bib:ref_1, ISO 704}}")
|
|
63
|
+
# # => { kind: "bib-ref", id: "ref_1", label: "ISO 704" }
|
|
64
|
+
module MentionParser
|
|
65
|
+
module_function
|
|
66
|
+
|
|
67
|
+
# Parse a single {{...}} mention into a canonical Hash.
|
|
68
|
+
#
|
|
69
|
+
# Returns nil if the input is not a valid mention string.
|
|
70
|
+
# Raises ArgumentError if the mention is malformed (e.g., unknown
|
|
71
|
+
# kind prefix).
|
|
72
|
+
def parse_mention(text)
|
|
73
|
+
return nil unless text.is_a?(String)
|
|
74
|
+
|
|
75
|
+
match = text.match(/\A\s*\{\{([^}]+)\}\}\s*\z/)
|
|
76
|
+
return nil unless match
|
|
77
|
+
|
|
78
|
+
content = match[1].strip
|
|
79
|
+
parse_content(content)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Parse the inside of a {{...}} mention (without the braces).
|
|
83
|
+
def parse_content(content)
|
|
84
|
+
content = content.to_s.strip
|
|
85
|
+
return nil if content.empty?
|
|
86
|
+
|
|
87
|
+
identifier, label = split_identifier_and_label(content)
|
|
88
|
+
dispatch_by_identifier(identifier, label)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def split_identifier_and_label(content)
|
|
92
|
+
return [content, nil] unless content.include?(",")
|
|
93
|
+
|
|
94
|
+
parts = content.split(",", 2)
|
|
95
|
+
[parts[0].strip, parts[1].to_s.strip]
|
|
96
|
+
end
|
|
97
|
+
private_class_method :split_identifier_and_label
|
|
98
|
+
|
|
99
|
+
def dispatch_by_identifier(identifier, label)
|
|
100
|
+
case identifier
|
|
101
|
+
when /\Alink:/i then parse_link(identifier, label)
|
|
102
|
+
when /\Aimage:/i then parse_image(identifier, label)
|
|
103
|
+
when /\Abib:/i then parse_bib(identifier, label)
|
|
104
|
+
when /\Acite:/i then parse_cite(identifier, label)
|
|
105
|
+
when /\A(fig|figure):/i then parse_entity(identifier, label, MentionKinds::FIG_REF, "fig:")
|
|
106
|
+
when /\A(table|tbl):/i then parse_entity(identifier, label, MentionKinds::TABLE_REF, "table:")
|
|
107
|
+
when /\A(formula|eq):/i then parse_entity(identifier, label, MentionKinds::FORMULA_REF, "formula:")
|
|
108
|
+
when /\Aurn:/i then parse_urn(identifier, label)
|
|
109
|
+
when /\A\d[\d.-]*\z/ then parse_local_concept(identifier, label)
|
|
110
|
+
else parse_designation(identifier, label)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
private_class_method :dispatch_by_identifier
|
|
114
|
+
|
|
115
|
+
def strip_label(label)
|
|
116
|
+
label.nil? || label.empty? ? nil : label
|
|
117
|
+
end
|
|
118
|
+
private_class_method :strip_label
|
|
119
|
+
|
|
120
|
+
def parse_link(identifier, label)
|
|
121
|
+
uri = identifier.sub(/\Alink:/i, "").strip
|
|
122
|
+
{ kind: MentionKinds::LINK_REF, uri: uri, label: strip_label(label) }
|
|
123
|
+
end
|
|
124
|
+
private_class_method :parse_link
|
|
125
|
+
|
|
126
|
+
def parse_image(identifier, label)
|
|
127
|
+
src = identifier.sub(/\Aimage:/i, "").strip
|
|
128
|
+
{ kind: MentionKinds::IMAGE_REF, src: src, alt: strip_label(label) }
|
|
129
|
+
end
|
|
130
|
+
private_class_method :parse_image
|
|
131
|
+
|
|
132
|
+
def parse_bib(identifier, label)
|
|
133
|
+
id = identifier.sub(/\Abib:/i, "").strip
|
|
134
|
+
{ kind: MentionKinds::BIB_REF, id: id, label: strip_label(label) }
|
|
135
|
+
end
|
|
136
|
+
private_class_method :parse_bib
|
|
137
|
+
|
|
138
|
+
def parse_cite(identifier, label)
|
|
139
|
+
id = strip_quote_wrapping(identifier.sub(/\Acite:/i, "").strip)
|
|
140
|
+
{ kind: MentionKinds::CITE_REF, id: id, label: strip_label(label) }
|
|
141
|
+
end
|
|
142
|
+
private_class_method :parse_cite
|
|
143
|
+
|
|
144
|
+
def parse_entity(identifier, label, kind, prefix)
|
|
145
|
+
id = identifier.sub(/\A(?:fig|figure|table|tbl|formula|eq):/i, "").strip
|
|
146
|
+
{ kind: kind, id: id, label: strip_label(label) }
|
|
147
|
+
end
|
|
148
|
+
private_class_method :parse_entity
|
|
149
|
+
|
|
150
|
+
def parse_urn(identifier, label)
|
|
151
|
+
{ kind: MentionKinds::URN_REF, urn: identifier, label: strip_label(label) }
|
|
152
|
+
end
|
|
153
|
+
private_class_method :parse_urn
|
|
154
|
+
|
|
155
|
+
def parse_local_concept(identifier, label)
|
|
156
|
+
{ kind: MentionKinds::LOCAL_CONCEPT_REF, id: identifier, label: strip_label(label) }
|
|
157
|
+
end
|
|
158
|
+
private_class_method :parse_local_concept
|
|
159
|
+
|
|
160
|
+
def parse_designation(identifier, label)
|
|
161
|
+
{ kind: MentionKinds::DESIGNATION_REF, designation: label || identifier }
|
|
162
|
+
end
|
|
163
|
+
private_class_method :parse_designation
|
|
164
|
+
|
|
165
|
+
# cite: identifiers may be wrapped in double quotes; the wrapping
|
|
166
|
+
# is removed and the doubled "“”" inside unescaped.
|
|
167
|
+
def strip_quote_wrapping(s)
|
|
168
|
+
return s unless s.start_with?('"') && s.end_with?('"') && s.length >= 2
|
|
169
|
+
|
|
170
|
+
s[1..-2].gsub('""', '"')
|
|
171
|
+
end
|
|
172
|
+
private_class_method :strip_quote_wrapping
|
|
173
|
+
end
|
|
174
|
+
end
|
|
@@ -1,21 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Glossarist
|
|
4
|
-
# Shared payload for every non-
|
|
5
|
-
#
|
|
6
|
-
#
|
|
4
|
+
# Shared payload for every non-concept entity — entities that are NOT
|
|
5
|
+
# concepts at all (Figure, Table, Formula), as opposed to non-verbal
|
|
6
|
+
# designations OF concepts (NonVerbRep).
|
|
7
7
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
# Terminology alignment (PROMPT-NOW P3):
|
|
9
|
+
# - Non-verbal refers to the modality of expression (non-verbal
|
|
10
|
+
# designation: symbol, formula expression). PROPERTIES OF concepts.
|
|
11
|
+
# - Non-concept refers to entities that are NOT concepts at all
|
|
12
|
+
# (Figure, Table, Formula). STANDALONE dataset entities.
|
|
13
|
+
#
|
|
14
|
+
# The four attributes here are the common a11y + provenance payload
|
|
15
|
+
# every non-concept entity carries, regardless of content type:
|
|
10
16
|
#
|
|
11
17
|
# - +caption+: localized short title (a11y / indexing).
|
|
12
18
|
# - +description+: localized long description (a11y screen readers).
|
|
13
19
|
# - +alt+: localized alternative text (a11y short screen-reader label).
|
|
14
20
|
# - +sources+: bibliographic sources for the representation.
|
|
15
21
|
#
|
|
16
|
-
# Identity (+id+, +identifier+) belongs on subclasses that have it;
|
|
17
|
-
#
|
|
18
|
-
class
|
|
22
|
+
# Identity (+id+, +identifier+) belongs on subclasses that have it;
|
|
23
|
+
# see SharedNonConceptEntity for the dataset-shared variant.
|
|
24
|
+
class NonConceptEntity < Lutaml::Model::Serializable
|
|
19
25
|
attribute :caption, :hash
|
|
20
26
|
attribute :description, :hash
|
|
21
27
|
attribute :alt, :hash
|
|
@@ -42,4 +48,7 @@ module Glossarist
|
|
|
42
48
|
from_yaml(File.read(path, encoding: "utf-8"))
|
|
43
49
|
end
|
|
44
50
|
end
|
|
51
|
+
|
|
52
|
+
# @deprecated Use NonConceptEntity instead. Kept for one release
|
|
53
|
+
# cycle to ease migration of downstream callers.
|
|
45
54
|
end
|
|
@@ -4,17 +4,26 @@ module Glossarist
|
|
|
4
4
|
# A concept-local non-verbal representation (ISO 10241-1 §6.5).
|
|
5
5
|
#
|
|
6
6
|
# NonVerbRep is the inline form attached directly to a concept's data.
|
|
7
|
-
# The dataset-shared form is Figure / Table / Formula. The two share
|
|
8
|
-
# same a11y + provenance payload via
|
|
9
|
-
# only in that it has no dataset-wide identity (no +id+, no
|
|
10
|
-
# — its identity is its position inside the parent
|
|
7
|
+
# The dataset-shared form is Figure / Table / Formula. The two share
|
|
8
|
+
# the same a11y + provenance payload via NonConceptEntity; NonVerbRep
|
|
9
|
+
# differs only in that it has no dataset-wide identity (no +id+, no
|
|
10
|
+
# +identifier+) — its identity is its position inside the parent
|
|
11
|
+
# concept.
|
|
12
|
+
#
|
|
13
|
+
# Note on terminology (PROMPT-NOW P3):
|
|
14
|
+
# NonVerbRep IS a non-verbal representation — it's a designation
|
|
15
|
+
# (a way of expressing a concept, distinct from verbal designation
|
|
16
|
+
# like terms). It is NOT a non-concept entity (which is a Figure /
|
|
17
|
+
# Table / Formula standalone). Both happen to inherit from
|
|
18
|
+
# NonConceptEntity for the shared a11y + provenance payload; the
|
|
19
|
+
# name NonVerbRep preserves the modality distinction.
|
|
11
20
|
#
|
|
12
21
|
# +type+ discriminates the kind of non-verbal content: "image", "table",
|
|
13
22
|
# or "formula". When +type+ is "image", +images+ carries one or more
|
|
14
23
|
# FigureImage variants (responsive, format fallback, dark/light). The
|
|
15
24
|
# caption/description/alt fields are localized (hash keyed by ISO 639
|
|
16
25
|
# code) for accessibility.
|
|
17
|
-
class NonVerbRep <
|
|
26
|
+
class NonVerbRep < NonConceptEntity
|
|
18
27
|
attribute :type, :string
|
|
19
28
|
attribute :images, FigureImage, collection: true, initialize_empty: true
|
|
20
29
|
|
|
@@ -223,8 +223,56 @@ module Glossarist
|
|
|
223
223
|
concept_refs + asset_refs
|
|
224
224
|
end
|
|
225
225
|
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
# AsciiDoc cross-reference: <<target>> or <<target, caption>>
|
|
227
|
+
#
|
|
228
|
+
# PROMPT-NOW P2: the `<<...,...>>` syntax has been overloaded for
|
|
229
|
+
# three different uses, only one of which is legitimate (non-concept
|
|
230
|
+
# entity xrefs). The other two (bibliography lookup, concept
|
|
231
|
+
# citation) bypass the unified resolution cascade.
|
|
232
|
+
#
|
|
233
|
+
# Behavior on encounter:
|
|
234
|
+
# 1. Emit a deprecation warning via Ruby's Warning module.
|
|
235
|
+
# 2. Re-parse to a typed reference based on the target's shape:
|
|
236
|
+
# - explicit fig:/table:/formula: prefix → typed entity xref
|
|
237
|
+
# - numeric id → local ConceptReference (legacy cite)
|
|
238
|
+
# - anything else → ConceptReference (let the resolver handle it)
|
|
239
|
+
# 3. Do NOT treat as a bibliography lookup. Bibliography is reached
|
|
240
|
+
# only via the new {{bib:id}} mention kind.
|
|
241
|
+
def resolve_asciidoc_xref(target, caption = nil)
|
|
242
|
+
target = target.to_s.strip
|
|
243
|
+
caption = caption.to_s.strip unless caption.nil?
|
|
244
|
+
warn_deprecated_xref(target, caption)
|
|
245
|
+
|
|
246
|
+
case target
|
|
247
|
+
when /\Afig(?:ure)?:/i then resolve_non_verbal_mention("fig:", target, caption, FigureReference)
|
|
248
|
+
when /\Atable:/i then resolve_non_verbal_mention("table:", target, caption, TableReference)
|
|
249
|
+
when /\Atbl:/i then resolve_non_verbal_mention("tbl:", target, caption, TableReference)
|
|
250
|
+
when /\Aformula:/i then resolve_non_verbal_mention("formula:", target, caption, FormulaReference)
|
|
251
|
+
when /\Aeq:/i then resolve_non_verbal_mention("eq:", target, caption, FormulaReference)
|
|
252
|
+
when /\A\d[\d.-]*\z/ then resolve_local(caption || target, target)
|
|
253
|
+
else resolve_designation(target, caption)
|
|
254
|
+
end
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def warn_deprecated_xref(target, caption)
|
|
258
|
+
return unless Warning.respond_to?(:warn)
|
|
259
|
+
|
|
260
|
+
suffix = ", #{caption}" if caption && !caption.empty?
|
|
261
|
+
Warning.warn(
|
|
262
|
+
"[glossarist] <<#{target}#{suffix}>> is deprecated. " \
|
|
263
|
+
"Use {{fig/table/formula:#{target}#{suffix}}} for non-concept entities, " \
|
|
264
|
+
"or {{cite:#{target}#{suffix}}} for concept citations.\n",
|
|
265
|
+
)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# {{bib:id}} → BibliographicReference. This is the explicit
|
|
269
|
+
# bibliography-lookup path (PROMPT-NOW P2). Replaces the old
|
|
270
|
+
# <<anchor>> bibliography shortcut which is now deprecated.
|
|
271
|
+
def resolve_bib_key(identifier, display)
|
|
272
|
+
cleaned = identifier.delete_prefix("bib:").strip
|
|
273
|
+
return nil if cleaned.empty?
|
|
274
|
+
|
|
275
|
+
BibliographicReference.new(anchor: cleaned)
|
|
228
276
|
end
|
|
229
277
|
|
|
230
278
|
def resolve_image_ref(path)
|
|
@@ -292,10 +340,13 @@ module Glossarist
|
|
|
292
340
|
) { |ext, content| ext.resolve_mention(content) }
|
|
293
341
|
|
|
294
342
|
# AsciiDoc cross-references: <<anchor>> or <<anchor,display text>>
|
|
343
|
+
# Captures both target and caption so resolve_asciidoc_xref can
|
|
344
|
+
# re-dispatch (PROMPT-NOW P2 — <<>> is deprecated, re-parse to
|
|
345
|
+
# the right kind based on target).
|
|
295
346
|
register_pattern(
|
|
296
347
|
name: :asciidoc_xref,
|
|
297
|
-
regex: /<<([^,>\n]+?)(?:,[^>\n]*)?>>/,
|
|
298
|
-
) { |ext, target| ext.resolve_asciidoc_xref(target) }
|
|
348
|
+
regex: /<<([^,>\n]+?)(?:,([^>\n]*))?>>/,
|
|
349
|
+
) { |ext, target, caption| ext.resolve_asciidoc_xref(target, caption) }
|
|
299
350
|
|
|
300
351
|
# Image references: image::path[] or image:path[]
|
|
301
352
|
register_pattern(
|
|
@@ -307,6 +358,10 @@ module Glossarist
|
|
|
307
358
|
ext.resolve_cite_key(identifier, display)
|
|
308
359
|
end
|
|
309
360
|
|
|
361
|
+
register_identifier_resolver("bib:") do |ext, identifier, display|
|
|
362
|
+
ext.resolve_bib_key(identifier, display)
|
|
363
|
+
end
|
|
364
|
+
|
|
310
365
|
register_identifier_resolver("fig:") do |ext, identifier, display|
|
|
311
366
|
ext.resolve_non_verbal_mention("fig:", identifier, display, FigureReference)
|
|
312
367
|
end
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Glossarist
|
|
4
|
-
# Dataset-shared non-
|
|
4
|
+
# Dataset-shared non-concept entity — a NonConceptEntity with a stable
|
|
5
5
|
# identity. Figure, Table, and Formula inherit from this; NonVerbRep
|
|
6
|
-
# (concept-local, positional) inherits from
|
|
6
|
+
# (concept-local, positional) inherits from NonConceptEntity directly.
|
|
7
7
|
#
|
|
8
8
|
# The +id+ is the stable identifier used for cross-referencing
|
|
9
9
|
# (e.g. +figures/fig_A.23.yaml+ → +id: fig_A.23+). The +identifier+ is
|
|
10
10
|
# the human-readable label (e.g. +"A.23"+) used for display and AsciiDoc
|
|
11
11
|
# xref targets like +<<fig_A.23>>+.
|
|
12
|
-
class
|
|
12
|
+
class SharedNonConceptEntity < NonConceptEntity
|
|
13
13
|
attribute :id, :string
|
|
14
14
|
attribute :identifier, :string
|
|
15
15
|
|
|
@@ -26,4 +26,7 @@ module Glossarist
|
|
|
26
26
|
[id].compact
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
|
+
|
|
30
|
+
# @deprecated Use SharedNonConceptEntity instead. Kept for one
|
|
31
|
+
# release cycle to ease migration.
|
|
29
32
|
end
|
data/lib/glossarist/table.rb
CHANGED
|
@@ -7,7 +7,7 @@ module Glossarist
|
|
|
7
7
|
# across concepts. The content is stored as structured data (rows/columns)
|
|
8
8
|
# or as a markup string (HTML, Markdown, AsciiDoc). Caption, description,
|
|
9
9
|
# and alt are localized for accessibility.
|
|
10
|
-
class Table <
|
|
10
|
+
class Table < SharedNonConceptEntity
|
|
11
11
|
attribute :content, :hash
|
|
12
12
|
attribute :format, :string
|
|
13
13
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Glossarist
|
|
4
|
+
module Validators
|
|
5
|
+
# Flags raw HTML in concept text that should be expressed as typed
|
|
6
|
+
# mention syntax instead. Raw HTML bypasses the renderer, is
|
|
7
|
+
# brittle, has no accessibility contract, and can embed
|
|
8
|
+
# deployment-specific URLs.
|
|
9
|
+
#
|
|
10
|
+
# Suggested replacements:
|
|
11
|
+
#
|
|
12
|
+
# <a href="URL">label</a> → {{link:URL, label}}
|
|
13
|
+
# <a href="URL">URL</a> → {{link:URL}}
|
|
14
|
+
# <img src="SRC"> → {{image:SRC}}
|
|
15
|
+
# <img src="SRC" alt="ALT">→ {{image:SRC, ALT}}
|
|
16
|
+
# <iframe src="URL"> → {{link:URL}}
|
|
17
|
+
#
|
|
18
|
+
# Usage:
|
|
19
|
+
# issues = Glossarist::Validators::NoRawHtml.call(concept_text)
|
|
20
|
+
# issues.each { |i| warn i[:message] }
|
|
21
|
+
class NoRawHtml
|
|
22
|
+
# Patterns are intentionally conservative — only tags that have
|
|
23
|
+
# a direct typed-mention replacement. Other HTML tags (<b>, <i>,
|
|
24
|
+
# <sup>, etc.) are left to the renderer's HTML sanitiser.
|
|
25
|
+
LINK_PATTERN = /<a\s+href="([^"]+)"[^>]*>([^<]*)<\/a>/i.freeze
|
|
26
|
+
IMAGE_PATTERN = /<img\s+src="([^"]+)"(?:\s+alt="([^"]*)")?[^>]*>/i.freeze
|
|
27
|
+
IFRAME_PATTERN = /<iframe\s+src="([^"]+)"[^>]*>/i.freeze
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
# @param text [String] the concept text to check
|
|
31
|
+
# @return [Array<Hash>] issues with severity, match, suggestion, message
|
|
32
|
+
def call(text)
|
|
33
|
+
return [] unless text.is_a?(String)
|
|
34
|
+
|
|
35
|
+
[].tap do |issues|
|
|
36
|
+
scan_links(text, issues)
|
|
37
|
+
scan_images(text, issues)
|
|
38
|
+
scan_iframes(text, issues)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def scan_links(text, issues)
|
|
45
|
+
text.scan(LINK_PATTERN) do |url, label|
|
|
46
|
+
suggestion = label && !label.strip.empty? ?
|
|
47
|
+
"{{link:#{url}, #{label.strip}}}" :
|
|
48
|
+
"{{link:#{url}}}"
|
|
49
|
+
issues << {
|
|
50
|
+
severity: "warning",
|
|
51
|
+
match: %(<a href="#{url}">#{label}</a>),
|
|
52
|
+
suggestion: suggestion,
|
|
53
|
+
message: "Use {{link:#{url}}} instead of raw <a> tags",
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def scan_images(text, issues)
|
|
59
|
+
text.scan(IMAGE_PATTERN) do |src, alt|
|
|
60
|
+
suggestion = alt && !alt.strip.empty? ?
|
|
61
|
+
"{{image:#{src}, #{alt.strip}}}" :
|
|
62
|
+
"{{image:#{src}}}"
|
|
63
|
+
issues << {
|
|
64
|
+
severity: "warning",
|
|
65
|
+
match: %(<img src="#{src}"#{" alt=\"#{alt}\"" if alt}>),
|
|
66
|
+
suggestion: suggestion,
|
|
67
|
+
message: "Use {{image:#{src}}} instead of raw <img> tags",
|
|
68
|
+
}
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def scan_iframes(text, issues)
|
|
73
|
+
text.scan(IFRAME_PATTERN).each do |match|
|
|
74
|
+
url = match.is_a?(Array) ? match[0] : match
|
|
75
|
+
issues << {
|
|
76
|
+
severity: "warning",
|
|
77
|
+
match: %(<iframe src="#{url}">),
|
|
78
|
+
suggestion: "{{link:#{url}}}",
|
|
79
|
+
message: "iframes are not supported as embeds; use {{link:}} instead",
|
|
80
|
+
}
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Glossarist
|
|
4
|
+
# Namespace for standalone validators (not Validation::Rule classes).
|
|
5
|
+
# These are opt-in utilities that consumers call explicitly — they
|
|
6
|
+
# are not auto-registered into the Validation::Rules pipeline.
|
|
7
|
+
module Validators
|
|
8
|
+
autoload :NoRawHtml, "glossarist/validators/no_raw_html"
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/glossarist/version.rb
CHANGED
data/lib/glossarist.rb
CHANGED
|
@@ -40,8 +40,8 @@ module Glossarist
|
|
|
40
40
|
autoload :ConceptEnricher, "glossarist/concept_enricher"
|
|
41
41
|
autoload :Config, "glossarist/config"
|
|
42
42
|
autoload :LocalizedString, "glossarist/localized_string"
|
|
43
|
-
autoload :
|
|
44
|
-
autoload :
|
|
43
|
+
autoload :NonConceptEntity, "glossarist/non_concept_entity"
|
|
44
|
+
autoload :SharedNonConceptEntity, "glossarist/shared_non_concept_entity"
|
|
45
45
|
autoload :NonVerbalReference, "glossarist/non_verbal_reference"
|
|
46
46
|
autoload :Figure, "glossarist/figure"
|
|
47
47
|
autoload :FigureImage, "glossarist/figure_image"
|
|
@@ -65,6 +65,8 @@ module Glossarist
|
|
|
65
65
|
autoload :ManagedConcept, "glossarist/managed_concept"
|
|
66
66
|
autoload :ManagedConceptCollection, "glossarist/managed_concept_collection"
|
|
67
67
|
autoload :ManagedConceptData, "glossarist/managed_concept_data"
|
|
68
|
+
autoload :MentionParser, "glossarist/mention_parser"
|
|
69
|
+
autoload :MentionKinds, "glossarist/mention_parser"
|
|
68
70
|
autoload :NonVerbRep, "glossarist/non_verb_rep"
|
|
69
71
|
autoload :Pronunciation, "glossarist/pronunciation"
|
|
70
72
|
autoload :RelatedConcept, "glossarist/related_concept"
|
|
@@ -86,10 +88,35 @@ module Glossarist
|
|
|
86
88
|
autoload :GlossaryDefinition, "glossarist/glossary_definition"
|
|
87
89
|
autoload :GlossaryStore, "glossarist/glossary_store"
|
|
88
90
|
autoload :Tasks, "glossarist/tasks"
|
|
91
|
+
autoload :Validators, "glossarist/validators"
|
|
89
92
|
|
|
90
93
|
LANG_CODES = %w[eng ara deu fra spa ita jpn kor pol por srp swe zho rus fin
|
|
91
94
|
dan nld msa nob nno].freeze
|
|
92
95
|
|
|
96
|
+
# @deprecated Use NonConceptEntity. Removed in next minor release.
|
|
97
|
+
def self.const_missing(name)
|
|
98
|
+
case name
|
|
99
|
+
when :NonVerbalEntity
|
|
100
|
+
warn "[glossarist] Glossarist::NonVerbalEntity is deprecated; " \
|
|
101
|
+
"use Glossarist::NonConceptEntity instead."
|
|
102
|
+
NonConceptEntity
|
|
103
|
+
when :SharedNonVerbalEntity
|
|
104
|
+
warn "[glossarist] Glossarist::SharedNonVerbalEntity is deprecated; " \
|
|
105
|
+
"use Glossarist::SharedNonConceptEntity instead."
|
|
106
|
+
SharedNonConceptEntity
|
|
107
|
+
else
|
|
108
|
+
super
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Parse a single {{...}} mention into a canonical Hash. Defined here
|
|
113
|
+
# (rather than via autoload) so calling Glossarist.parse_mention(str)
|
|
114
|
+
# triggers the MentionParser autoload chain transparently — method
|
|
115
|
+
# calls do not fire autoloads on their own.
|
|
116
|
+
def self.parse_mention(text)
|
|
117
|
+
MentionParser.parse_mention(text)
|
|
118
|
+
end
|
|
119
|
+
|
|
93
120
|
SCHEMA_VERSION = "3"
|
|
94
121
|
V3_SCHEMA_VERSION = "3"
|
|
95
122
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: glossarist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.13.
|
|
4
|
+
version: 2.13.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: lutaml-model
|
|
@@ -195,6 +195,7 @@ files:
|
|
|
195
195
|
- CLAUDE.md
|
|
196
196
|
- Gemfile
|
|
197
197
|
- LICENSE.txt
|
|
198
|
+
- PROMPT-NOW.md
|
|
198
199
|
- README.adoc
|
|
199
200
|
- Rakefile
|
|
200
201
|
- config.yml
|
|
@@ -291,8 +292,9 @@ files:
|
|
|
291
292
|
- lib/glossarist/managed_concept.rb
|
|
292
293
|
- lib/glossarist/managed_concept_collection.rb
|
|
293
294
|
- lib/glossarist/managed_concept_data.rb
|
|
295
|
+
- lib/glossarist/mention_parser.rb
|
|
296
|
+
- lib/glossarist/non_concept_entity.rb
|
|
294
297
|
- lib/glossarist/non_verb_rep.rb
|
|
295
|
-
- lib/glossarist/non_verbal_entity.rb
|
|
296
298
|
- lib/glossarist/non_verbal_reference.rb
|
|
297
299
|
- lib/glossarist/pronunciation.rb
|
|
298
300
|
- lib/glossarist/rdf.rb
|
|
@@ -352,7 +354,7 @@ files:
|
|
|
352
354
|
- lib/glossarist/schema_migration/v0_to_v1.rb
|
|
353
355
|
- lib/glossarist/schema_migration/v2_to_v3.rb
|
|
354
356
|
- lib/glossarist/section.rb
|
|
355
|
-
- lib/glossarist/
|
|
357
|
+
- lib/glossarist/shared_non_concept_entity.rb
|
|
356
358
|
- lib/glossarist/sts.rb
|
|
357
359
|
- lib/glossarist/sts/extracted_designation.rb
|
|
358
360
|
- lib/glossarist/sts/extracted_lang_set.rb
|
|
@@ -480,6 +482,8 @@ files:
|
|
|
480
482
|
- lib/glossarist/validation/shacl_validator.rb
|
|
481
483
|
- lib/glossarist/validation/validation_issue.rb
|
|
482
484
|
- lib/glossarist/validation_result.rb
|
|
485
|
+
- lib/glossarist/validators.rb
|
|
486
|
+
- lib/glossarist/validators/no_raw_html.rb
|
|
483
487
|
- lib/glossarist/version.rb
|
|
484
488
|
- memory/project-status.md
|
|
485
489
|
- relaton-bib-2.0.0.gem
|