File: block_string.rb

package info (click to toggle)
ruby-graphql 2.2.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 9,584 kB
  • sloc: ruby: 67,505; ansic: 1,753; yacc: 831; javascript: 331; makefile: 6
file content (115 lines) | stat: -rw-r--r-- 3,157 bytes parent folder | download
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
# frozen_string_literal: true
module GraphQL
  module Language
    module BlockString
      # Remove leading and trailing whitespace from a block string.
      # See "Block Strings" in https://github.com/facebook/graphql/blob/master/spec/Section%202%20--%20Language.md
      def self.trim_whitespace(str)
        # Early return for the most common cases:
        if str == ""
          return "".dup
        elsif !(has_newline = str.include?("\n")) && !(str.start_with?(" "))
          return str
        end

        lines = has_newline ? str.split("\n") : [str]
        common_indent = nil

        # find the common whitespace
        lines.each_with_index do |line, idx|
          if idx == 0
            next
          end
          line_length = line.size
          line_indent = if line.match?(/\A  [^ ]/)
            2
          elsif line.match?(/\A    [^ ]/)
            4
          elsif line.match?(/\A[^ ]/)
            0
          else
            line[/\A */].size
          end
          if line_indent < line_length && (common_indent.nil? || line_indent < common_indent)
            common_indent = line_indent
          end
        end

        # Remove the common whitespace
        if common_indent && common_indent > 0
          lines.each_with_index do |line, idx|
            if idx == 0
              next
            else
              line.slice!(0, common_indent)
            end
          end
        end

        # Remove leading & trailing blank lines
        while lines.size > 0 && contains_only_whitespace?(lines.first)
          lines.shift
        end
        while lines.size > 0 && contains_only_whitespace?(lines.last)
          lines.pop
        end

        # Rebuild the string
        lines.size > 1 ? lines.join("\n") : (lines.first || "".dup)
      end

      def self.print(str, indent: '')
        line_length = 120 - indent.length
        block_str = "".dup
        triple_quotes = "\"\"\"\n"
        block_str << indent
        block_str << triple_quotes

        if str.include?("\n")
          str.split("\n") do |line|
            if line == ''
              block_str << "\n"
            else
              break_line(line, line_length) do |subline|
                block_str << indent
                block_str << subline
                block_str << "\n"
              end
            end
          end
        else
          break_line(str, line_length) do |subline|
            block_str << indent
            block_str << subline
            block_str << "\n"
          end
        end

        block_str << indent
        block_str << triple_quotes
      end

      private

      def self.break_line(line, length)
        return yield(line) if line.length < length + 5

        parts = line.split(Regexp.new("((?: |^).{15,#{length - 40}}(?= |$))"))
        return yield(line) if parts.length < 4

        yield(parts.slice!(0, 3).join)

        parts.each_with_index do |part, i|
          next if i % 2 == 1
          yield "#{part[1..-1]}#{parts[i + 1]}"
        end

        nil
      end

      def self.contains_only_whitespace?(line)
        line.match?(/^\s*$/)
      end
    end
  end
end