File: link_spec.rb

package info (click to toggle)
ruby-asciidoctor-pdf 2.3.19-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,972 kB
  • sloc: ruby: 44,316; sh: 133; java: 45; makefile: 4
file content (311 lines) | stat: -rw-r--r-- 13,680 bytes parent folder | download | duplicates (2)
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# frozen_string_literal: true

require_relative 'spec_helper'

describe 'Asciidoctor::PDF::Converter - Link' do
  context 'URL' do
    it 'should convert a raw URL to a link' do
      input = 'The home page for Asciidoctor is located at https://asciidoctor.org.'
      pdf = to_pdf input
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'https://asciidoctor.org'

      pdf = to_pdf input, analyze: true
      link_text = (pdf.find_text 'https://asciidoctor.org')[0]
      (expect link_text).not_to be_nil
      (expect link_text[:font_color]).to eql '428BCA'
      (expect link_annotation).to annotate link_text
    end

    it 'should decode character references in the href' do
      input = 'https://github.com/asciidoctor/asciidoctor-pdf/milestones?direction=asc&sort=<>&state=open'
      pdf = to_pdf input
      text = (pdf.page 1).text
      (expect text).to eql input
      link = (get_annotations pdf, 1)[0]
      (expect link[:A][:URI]).to eql input
    end

    it 'should convert link surrounded in double smart quotes' do
      pdf = to_pdf '"`https://asciidoctor.org[Asciidoctor]`"'
      text = (pdf.page 1).text
      (expect text).to eql %(\u201cAsciidoctor\u201d)
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link = annotations[0]
      (expect link[:A][:URI]).to eql 'https://asciidoctor.org'
    end

    it 'should convert link surrounded in single smart quotes' do
      pdf = to_pdf %('`https://asciidoctor.org[Asciidoctor]`')
      text = (pdf.page 1).text
      (expect text).to eql %(\u2018Asciidoctor\u2019)
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link = annotations[0]
      (expect link[:A][:URI]).to eql 'https://asciidoctor.org'
    end

    it 'should not encode hash that precedes the fragment in a URL' do
      url_with_hash = 'https://github.com/asciidoctor/asciidoctor-pdf/blob/main/docs/theming-guide.adoc#fonts'
      pdf = to_pdf %(Learn how to configure #{url_with_hash}[].)
      text = (pdf.page 1).text
      (expect text).to eql %(Learn how to configure #{url_with_hash.sub 'theming-guide', "theming-\nguide"}.)
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 2
      (expect annotations[0][:A][:URI]).to eql url_with_hash
      (expect annotations[1][:A][:URI]).to eql url_with_hash
    end

    it 'should split bare URL on breakable characters' do
      [
        'the URL on this line will get split on the ? char https://github.com/asciidoctor/asciidoctor/issues?|q=milestone%3Av2.0.x',
        'the URL on this line will get split on the / char instead https://github.com/asciidoctor/asciidoctor/|issues?q=milestone%3Av2.0.x',
        'the URL on this line will get split on the # char https://github.com/asciidoctor/asciidoctor/issues#|milestone%3Av2.0.x',
      ].each do |text|
        before, after = text.split '|', 2
        pdf = to_pdf %(#{before}#{after}), analyze: true
        lines = pdf.lines
        (expect lines).to have_size 2
        (expect lines[0]).to end_with before
        (expect lines[1]).to start_with after
      end
    end

    it 'should not break on last character of bare URL' do
      pdf = to_pdf <<~'EOS', analyze: true
      https://this.is.a.very.long.url.that.is.going.to.be.split.at.a.breakable.location.com/verylongpathname?a[]
      EOS
      lines = pdf.lines
      (expect lines).to have_size 2
      (expect lines[0]).to end_with '/'
      (expect lines[1]).to eql 'verylongpathname?a'
    end

    it 'should not attempt to break URL when URL is a bare scheme' do
      pdf = to_pdf 'link:https://[]', analyze: true
      lines = pdf.lines
      (expect lines).to have_size 1
      (expect lines[0]).to eql 'https://'
    end

    it 'should not split bare URL when using an AFM font' do
      pdf = to_pdf <<~'EOS', pdf_theme: { base_font_family: 'Helvetica' }, analyze: true
      this line contains a URL that falls at the end of the line and yet cannot be split https://goo.gl/search/asciidoctor
      EOS
      lines = pdf.lines
      (expect lines).to have_size 2
      (expect lines[1]).to eql 'https://goo.gl/search/asciidoctor'
    end

    it 'should not split bare URL after scheme' do
      pdf = to_pdf <<~'EOS', analyze: true
      this line contains a URL that falls at the end of the line that is not split after the scheme https://goo.gl/search/asciidoctor
      EOS
      lines = pdf.lines
      (expect lines).to have_size 2
      (expect lines[1]).to eql 'https://goo.gl/search/asciidoctor'
    end

    it 'should reveal URL of link when media=print or media=prepress' do
      %w(print prepress).each do |media|
        pdf = to_pdf <<~'EOS', attribute_overrides: { 'media' => media }, analyze: true
        https://asciidoctor.org[Asciidoctor] is a text processor.
        EOS

        (expect pdf.lines).to eql ['Asciidoctor [https://asciidoctor.org] is a text processor.']
      end
    end

    it 'should reveal URL of link when show-link-uri is set' do
      pdf = to_pdf <<~'EOS', analyze: true
      :show-link-uri:

      https://asciidoctor.org[Asciidoctor] is a text processor.
      EOS

      (expect pdf.lines).to eql ['Asciidoctor [https://asciidoctor.org] is a text processor.']
    end

    it 'should not reveal URL of link when show-link-uri is unset in document even when media is print or prepress' do
      %w(print prepress).each do |media|
        pdf = to_pdf <<~'EOS', attribute_overrides: { 'media' => media }, analyze: true
        :!show-link-uri:

        https://asciidoctor.org[Asciidoctor] is a text processor.
        EOS

        (expect pdf.lines).to eql ['Asciidoctor is a text processor.']
      end
    end

    it 'should not reveal URL of link when show-link-uri is unset from API even media is print or prepress' do
      %w(print prepress).each do |media|
        pdf = to_pdf <<~'EOS', attribute_overrides: { 'media' => media, 'show-link-uri' => nil }, analyze: true
        https://asciidoctor.org[Asciidoctor] is a text processor.
        EOS

        (expect pdf.lines).to eql ['Asciidoctor is a text processor.']
      end
    end

    it 'should split revealed URL on breakable characters when media=print, media=prepress, or show-link-uri is set' do
      inputs = [
        'the URL on this line will get split on the ? char https://github.com/asciidoctor/asciidoctor/issues?|q=milestone%3Av2.0.x[link]',
        'the URL on this line will get split on the / char instead https://github.com/asciidoctor/asciidoctor/|issues?q=milestone%3Av2.0.x[link]',
        'the URL on this line will get split on the # char https://github.com/asciidoctor/asciidoctor/issues#|milestone%3Av2.0.x[link]',
      ]
      [{ 'media' => 'print' }, { 'media' => 'prepress' }, { 'show-link-uri' => '' }].each do |attribute_overrides|
        inputs.each do |text|
          before, after = text.split '|', 2
          expected_before = before.sub 'https://', 'link [ https://'
          expected_after = after.sub '[link]', ']'
          pdf = to_pdf %(#{before}#{after}), attribute_overrides: attribute_overrides, analyze: true
          lines = pdf.lines
          (expect lines).to have_size 2
          (expect lines[0]).to end_with expected_before
          (expect lines[1]).to start_with expected_after
        end
      end
    end
  end

  context 'Email' do
    it 'should convert bare email address to link' do
      input = 'Send a message to doc.writer@example.org.'
      pdf = to_pdf input
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'mailto:doc.writer@example.org'
      pdf = to_pdf input, analyze: true
      link_text = pdf.find_unique_text 'doc.writer@example.org'
      (expect link_text).not_to be_nil
      (expect link_text[:font_color]).to eql '428BCA'
      (expect link_annotation).to annotate link_text
    end

    it 'should create email address link' do
      input = 'Send a message to mailto:doc.writer@example.org[Doc Writer].'
      pdf = to_pdf input
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'mailto:doc.writer@example.org'
      (expect (pdf.page 1).text).to include 'Doc Writer'
      pdf = to_pdf input, analyze: true
      link_text = pdf.find_unique_text 'Doc Writer'
      (expect link_text).not_to be_nil
      (expect link_text[:font_color]).to eql '428BCA'
      (expect link_annotation).to annotate link_text
    end

    it 'should show mailto address of bare email when media=prepress' do
      input = 'Send message to doc.writer@example.org.'
      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress' }
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'mailto:doc.writer@example.org'

      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress' }, analyze: true
      (expect pdf.lines[0]).to eql 'Send message to doc.writer@example.org.'
    end

    it 'should show mailto address of email link when media=prepress' do
      input = 'Send message to mailto:doc.writer@example.org[Doc Writer].'
      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress' }
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'mailto:doc.writer@example.org'

      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress' }, analyze: true
      (expect pdf.lines[0]).to eql 'Send message to Doc Writer [mailto:doc.writer@example.org].'
    end

    it 'should not show mailto address of bare email when media=prepress and hide-uri-scheme is set' do
      input = 'Send message to doc.writer@example.org.'
      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress', 'hide-uri-scheme' => '' }
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'mailto:doc.writer@example.org'

      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress', 'hide-uri-scheme' => '' }, analyze: true
      (expect pdf.lines[0]).to eql 'Send message to doc.writer@example.org.'
    end

    it 'should not use mailto prefix on email address of email link when media=prepress and hide-uri-scheme is set' do
      input = 'Send message to mailto:doc.writer@example.org[Doc Writer].'
      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress', 'hide-uri-scheme' => '' }
      annotations = get_annotations pdf, 1
      (expect annotations).to have_size 1
      link_annotation = annotations[0]
      (expect link_annotation[:Subtype]).to be :Link
      (expect link_annotation[:A][:URI]).to eql 'mailto:doc.writer@example.org'

      pdf = to_pdf input, attribute_overrides: { 'media' => 'prepress', 'hide-uri-scheme' => '' }, analyze: true
      (expect pdf.lines[0]).to eql 'Send message to Doc Writer [doc.writer@example.org].'
    end
  end

  context 'Unknown' do
    it 'should show warning if anchor type is unknown' do
      linkme_inline_macro_impl = proc do
        named 'linkme'
        process do |parent, target|
          create_anchor parent, target, type: :unknown
        end
      end
      opts = { extension_registry: Asciidoctor::Extensions.create { inline_macro(&linkme_inline_macro_impl) } }
      (expect do
        pdf = to_pdf 'before linkme:foobar[] after', (opts.merge analyze: true)
        (expect pdf.lines).to eql ['before after']
      end).to log_message severity: :WARN, message: 'unknown anchor type: :unknown'
    end
  end

  context 'Theming' do
    it 'should apply text decoration to link defined by theme' do
      pdf_theme = {
        link_font_style: 'italic',
        link_text_decoration: 'underline',
      }
      input = 'The home page for Asciidoctor is located at https://asciidoctor.org.'
      pdf = to_pdf input, pdf_theme: pdf_theme, analyze: :line
      lines = pdf.lines
      (expect lines).to have_size 1
      underline = lines[0]
      pdf = to_pdf input, pdf_theme: pdf_theme, analyze: true
      link_text = (pdf.find_text 'https://asciidoctor.org')[0]
      (expect link_text[:font_name]).to eql 'NotoSerif-Italic'
      (expect link_text[:font_color]).to eql underline[:color]
      (expect underline[:width]).to be_nil
    end

    it 'should allow theme to set width and color of text decoration' do
      [:base_text_decoration_width, :link_text_decoration_width].each do |key|
        pdf_theme = {
          link_text_decoration: 'underline',
          link_text_decoration_color: '0000FF',
        }
        pdf_theme[key] = 0.5
        pdf = to_pdf 'The home page for Asciidoctor is located at https://asciidoctor.org.', pdf_theme: pdf_theme, analyze: :line
        lines = pdf.lines
        (expect lines).to have_size 1
        underline = lines[0]
        (expect underline[:color]).to eql '0000FF'
        (expect underline[:width]).to eql 0.5
      end
    end
  end
end