Module: MarkdownServer::Unhide
- Defined in:
- lib/markdown_server/unhide.rb
Defined Under Namespace
Classes: CompileError, Rule
Class Method Summary collapse
- .compile(raw_entries) ⇒ Object
- .compile_one(raw) ⇒ Object
-
.entry_step(parent_mode, parent_segs, entry_name, rules) ⇒ Object
Amortized step for an enumeration.
-
.match_at(path_segs, i, rules) ⇒ Object
Returns :leaf if any rule matches segment i as its leaf, :prefix if any rule matches segment i as a navigational prefix, :none otherwise.
- .normalize_segments(path) ⇒ Object
- .restricted?(name) ⇒ Boolean
- .step(mode, path_segs, i, seg, rules) ⇒ Object
-
.visible?(path_segments, rules) ⇒ Boolean
Cold check: walks segment by segment from root, tracking mode.
Class Method Details
.compile(raw_entries) ⇒ Object
7 8 9 |
# File 'lib/markdown_server/unhide.rb', line 7 def self.compile(raw_entries) Array(raw_entries).compact.map { |e| compile_one(e) }.uniq end |
.compile_one(raw) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/markdown_server/unhide.rb', line 11 def self.compile_one(raw) entry = raw.to_s.strip raise CompileError, "unhide entry is empty" if entry.empty? if entry.start_with?("@/") path = entry.sub(%r{^@/+}, "") raise CompileError, "unhide entry '#{raw}' has no path after '@/'" if path.empty? segments = normalize_segments(path) raise CompileError, "unhide entry '#{raw}' has no usable segments" if segments.empty? Rule.new(:anchored, segments) else if entry.start_with?("/") raise CompileError, "unhide entry '#{raw}' has a leading '/'. " \ "Use '@/...' for project-root-anchored, or omit the slash for any-depth match." end segments = normalize_segments(entry) raise CompileError, "unhide entry '#{raw}' has no usable segments" if segments.empty? Rule.new(segments.length == 1 ? :basename : :suffix, segments) end end |
.entry_step(parent_mode, parent_segs, entry_name, rules) ⇒ Object
Amortized step for an enumeration. parent_mode and parent_segs are known from the enclosing recursion; this checks one entry. Returns [visible, child_mode].
87 88 89 90 |
# File 'lib/markdown_server/unhide.rb', line 87 def self.entry_step(parent_mode, parent_segs, entry_name, rules) path_segs = parent_segs + [entry_name] step(parent_mode, path_segs, path_segs.length - 1, entry_name, rules) end |
.match_at(path_segs, i, rules) ⇒ Object
Returns :leaf if any rule matches segment i as its leaf, :prefix if any rule matches segment i as a navigational prefix, :none otherwise.
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/markdown_server/unhide.rb', line 45 def self.match_at(path_segs, i, rules) best = :none rules.each do |r| case r.kind when :basename return :leaf if r.segments[0] == path_segs[i] when :suffix r.segments.length.times do |k| next unless i >= k next unless path_segs[(i - k)..i] == r.segments[0..k] if k + 1 == r.segments.length return :leaf else best = :prefix end end when :anchored if i < r.segments.length && path_segs[0..i] == r.segments[0..i] if i + 1 == r.segments.length return :leaf else best = :prefix end end end end best end |
.normalize_segments(path) ⇒ Object
33 34 35 |
# File 'lib/markdown_server/unhide.rb', line 33 def self.normalize_segments(path) path.split("/").reject(&:empty?) end |
.restricted?(name) ⇒ Boolean
37 38 39 40 |
# File 'lib/markdown_server/unhide.rb', line 37 def self.restricted?(name) return false if name.nil? || name.empty? name.start_with?(".") || MarkdownServer::EXCLUDED.include?(name) end |
.step(mode, path_segs, i, seg, rules) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/markdown_server/unhide.rb', line 92 def self.step(mode, path_segs, i, seg, rules) restricted = restricted?(seg) if restricted case match_at(path_segs, i, rules) when :leaf then [true, :open] when :prefix then [true, :narrow] else [false, nil] end else if mode == :open [true, :open] else case match_at(path_segs, i, rules) when :leaf then [true, :open] when :prefix then [true, :narrow] else [false, nil] end end end end |
.visible?(path_segments, rules) ⇒ Boolean
Cold check: walks segment by segment from root, tracking mode. Returns true iff every segment of path_segments is admitted.
76 77 78 79 80 81 82 83 |
# File 'lib/markdown_server/unhide.rb', line 76 def self.visible?(path_segments, rules) mode = :open path_segments.each_with_index do |seg, i| visible, mode = step(mode, path_segments, i, seg, rules) return false unless visible end true end |