Module: Coradoc::Reference::Address::Path

Defined in:
lib/coradoc/reference/address/path.rb

Overview

Inter-document path — a document identifier plus optional fragment. Matches document-ID-shaped barewords (uppercase + dash + digit, e.g. "ELF-5005-1") and relative/absolute file paths ("images/foo.png", "../shared/common.adoc"). Locality is carried in fragment.

"ELF-5005-1"          => path target "ELF-5005-1"
"ELF-5005-1#sec-3"    => path target "ELF-5005-1", fragment "sec-3"
"images/foo.png"      => path target "images/foo.png"

Constant Summary collapse

DOC_ID_PATTERN =

Doc-ID pattern: uppercase-led bareword ("ELF-5005-1"). Used together with a separate digit scan — two linear passes, no ambiguous adjacent quantifiers (polynomial-ReDoS-safe).

/\A[A-Z][A-Z0-9_\-]*\z/
LOOSE_PATTERN =

Loose pattern used by parse when the scheme is already chosen (via hint). Accepts any non-empty target plus optional fragment.

/\A([^#]+)(?:#(.*))?\z/

Class Method Summary collapse

Class Method Details

.matches?(raw) ⇒ Boolean

Returns:

  • (Boolean)


30
31
32
33
34
35
36
37
38
39
40
# File 'lib/coradoc/reference/address/path.rb', line 30

def matches?(raw)
  return false if raw.nil? || raw.empty?

  value = raw.to_s
  return true if value.include?('/')

  # Document IDs are uppercase-led and contain at least one digit
  # (what distinguishes them from anchors like "SECTION").
  id_part = value.split('#', 2).first
  DOC_ID_PATTERN.match?(id_part) && id_part.match?(/\d/)
end

.normalize_fragment(fragment) ⇒ Object



60
61
62
# File 'lib/coradoc/reference/address/path.rb', line 60

def normalize_fragment(fragment)
  fragment&.empty? ? nil : fragment
end

.parse(raw) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/coradoc/reference/address/path.rb', line 42

def parse(raw)
  match = LOOSE_PATTERN.match(raw.to_s)
  raise Address::ParseError, "Invalid path: #{raw.inspect}" unless match

  Address.new(
    scheme: 'path',
    target: match[1],
    fragment: normalize_fragment(match[2])
  )
end

.scheme_nameObject



26
27
28
# File 'lib/coradoc/reference/address/path.rb', line 26

def scheme_name
  :path
end

.serialize(address) ⇒ Object



53
54
55
56
57
58
# File 'lib/coradoc/reference/address/path.rb', line 53

def serialize(address)
  base = address.target.to_s
  return base unless address.fragment && !address.fragment.empty?

  "#{base}##{address.fragment}"
end