Module: OKF::Markdown::Citations
- Defined in:
- lib/okf/markdown/citations.rb
Overview
Parses the retired # Citations section of a v0.1 concept body (§13.1): the
block of external sources listed at the bottom of a document. Pure and
fence-aware, mirroring Links; it reuses Links.extract to pull the citation link
targets so citations and cross-links agree on what counts as a link.
Constant Summary collapse
- HEADING =
A markdown ATX heading line: 1–6
#, whitespace, then the heading text. /\A(\#{1,6})\s+(.*?)\s*\z/.freeze
- CITATIONS =
/\ACitations\z/i.freeze
- URL_ITEM =
A list item (or lone line) that is only a URL — the v0.1 spelling the v0.2 SPEC's own Appendix A uses — and the same item written as an autolink (which also admits mailto:). Both are citations with no text to lift into a title; both compose their scheme from Links' one grammar, so citations and cross-links answer the case question alike.
%r{\A(?:[-*+]\s+)?(#{Links::SCHEME_NAME}://\S+)\z}.freeze
- AUTOLINK_ITEM =
/\A(?:[-*+]\s+)?<(#{Links::SCHEME_NAME}:[^>\s]+)>\z/.freeze
Class Method Summary collapse
-
.entries(body) ⇒ Object
The citation entries as { text:, target: } pairs, in document order — what Concept#sources lifts into { "title", "resource" } mappings.
-
.section(body) ⇒ Object
The body text under a
# Citationsheading, up to the next heading at the same or higher level, or nil when there is no Citations section.
Class Method Details
.entries(body) ⇒ Object
The citation entries as { text:, target: } pairs, in document order — what Concept#sources lifts into { "title", "resource" } mappings. Three item forms (§13.1): labelled links carry their text; bare-URL and autolink items have none; a reference-style citation still yields its target through Links.extract.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/okf/markdown/citations.rb', line 55 def entries(body) text = section(body).to_s definitions = Links.reference_definitions(text) found = [] Links.each_prose_line(text) do |line| item = line.strip match = AUTOLINK_ITEM.match(item) || URL_ITEM.match(item) if match found << { text: "", target: match[1] } next end # Both grammars scan the same line and merge by offset, so the list # keeps document order *within* a line too — scanning all inline # links before any reference links reversed a mixed line's own order, # and a migration lifting sources off this output writes the list # permanently. Reference items resolve in place, text kept. items = [] line.scan(Links::INLINE_LINK) do |label, target| items << [ Regexp.last_match.begin(0), { text: label.to_s.strip, target: target } ] end line.scan(Links::REFERENCE_LINK) do |label, explicit| target = definitions[(explicit.empty? ? label : explicit).strip.downcase] items << [ Regexp.last_match.begin(0), { text: label.to_s.strip, target: target } ] if target end items.sort_by(&:first).each { |_, entry| found << entry } end found end |
.section(body) ⇒ Object
The body text under a # Citations heading, up to the next heading at the
same or higher level, or nil when there is no Citations section.
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/okf/markdown/citations.rb', line 25 def section(body) lines = [] level = nil in_fence = false body.to_s.each_line do |line| if Links::FENCE.match?(line.strip) in_fence = !in_fence lines << line unless level.nil? next end heading = in_fence ? nil : HEADING.match(line.strip) if level.nil? next unless heading && CITATIONS.match?(heading[2]) level = heading[1].length elsif heading && heading[1].length <= level break else lines << line end end lines.join unless level.nil? end |