Welcome to mirror list, hosted at ThFree Co, Russian Federation.

anchors.rb « checks « lib - gitlab.com/gitlab-org/gitlab-docs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 7c56eff4bf8b87418442f80ff809125c85da1c65 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module Gitlab
  module Docs
    module Nanoc
      def self.config
        @config ||= YAML.load(File.read('nanoc.yaml'))
      end

      def self.output_dir
        config.fetch('output_dir')
      end
    end

    class Page
      attr_reader :file

      def initialize(file)
        @file = file
      end

      def exists?
        File.exists?(@file)
      end

      def directory
        File.dirname(@file)
      end

      def content
        raise unless exists?

        @content ||= File.read(@file)
      end

      def document
        raise if content.to_s.empty?

        @doc ||= Nokogiri::HTML(content)
      end

      def links
        @links ||= document.css(:a).map do |link|
          Gitlab::Docs::Link.new(link, self)
        end
      end

      def has_anchor?(name)
        document.at_css(%Q{[id="#{name}"]})
      end

      def self.build(path)
        if path.end_with?('.html')
          new(path)
        else
          new(File.join(path, 'index.html'))
        end
      end
    end

    class Link
      attr_reader :link, :href, :page

      def initialize(link, page)
        @link = link
        @href = link[:href]
        @page = page
      end

      def to_anchor?
        @href.to_s.include?('#')
      end

      def anchor_name
        raise ArguentError unless to_anchor?

        @href.to_s.partition('#').last
      end

      def internal_anchor?
        raise ArguentError unless to_anchor?

        @href.to_s.partition('#').first.empty?
      end

      def internal?
        @href.to_s.length > 0 && !@href.include?(':')
      end

      def path
        @href.to_s.partition('#').first
      end

      def absolute_path
        raise unless internal?

        if @href.start_with?('/')
          Gitlab::Docs::Nanoc.output_dir + path
        else
          ::File.expand_path(path, @page.directory)
        end
      end

      def destination_page
        if internal_anchor?
          @page
        else
          Gitlab::Docs::Page.build(absolute_path)
        end
      end

      def source_file
        @page.file
      end

      def destination_file
        destination_page.file
      end

      def destination_page_not_found?
        !destination_page.exists?
      end

      def destination_anchor_not_found?
        !destination_page.has_anchor?(anchor_name)
      end
    end
  end
end

Nanoc::Check.define(:internal_anchors) do
  output_html_filenames.each do |file|
    Gitlab::Docs::Page.new(file).links.each do |link|
      next unless link.internal?
      next unless link.to_anchor?
      next if link.anchor_name == 'markdown-toc'

      if link.destination_page_not_found?
        add_issue <<~ERROR
          Destination page not found!
                - link `#{link.href}`
                - destination `#{link.destination_file}`
                - source file `#{link.source_file}`
        ERROR
      elsif link.destination_anchor_not_found?
        add_issue <<~ERROR
          Broken anchor detected!
                - anchor `##{link.anchor_name}`
                - link `#{link.href}`
                - source file `#{link.source_file}`
                - destination `#{link.destination_file}`
        ERROR

      end
    end
  end
end