2019-10-12 21:52:04 +05:30
# frozen_string_literal: true
2015-09-11 14:41:01 +05:30
require 'spec_helper'
require 'nokogiri'
module Gitlab
2020-07-28 23:09:34 +05:30
RSpec . describe Asciidoc do
2019-09-04 21:01:54 +05:30
include FakeBlobHelpers
before do
allow_any_instance_of ( ApplicationSetting ) . to receive ( :current ) . and_return ( :: ApplicationSetting . create_from_defaults )
end
2015-09-11 14:41:01 +05:30
2022-03-02 08:16:31 +05:30
context " without project " do
let ( :input ) { '<b>ascii</b>' }
let ( :context ) { { } }
let ( :html ) { 'H<sub>2</sub>O' }
it " converts the input using Asciidoctor and default options " do
expected_asciidoc_opts = {
safe : :secure ,
backend : :gitlab_html5 ,
attributes : described_class :: DEFAULT_ADOC_ATTRS . merge ( { " kroki-server-url " = > nil } ) ,
extensions : be_a ( Proc )
}
expect ( Asciidoctor ) . to receive ( :convert )
. with ( input , expected_asciidoc_opts ) . and_return ( html )
expect ( render ( input , context ) ) . to eq ( html )
end
2015-09-11 14:41:01 +05:30
2022-03-02 08:16:31 +05:30
context " with asciidoc_opts " do
it " merges the options with default ones " do
2015-09-11 14:41:01 +05:30
expected_asciidoc_opts = {
2017-08-17 22:00:37 +05:30
safe : :secure ,
backend : :gitlab_html5 ,
2021-02-22 17:27:13 +05:30
attributes : described_class :: DEFAULT_ADOC_ATTRS . merge ( { " kroki-server-url " = > nil } ) ,
2019-09-04 21:01:54 +05:30
extensions : be_a ( Proc )
2015-09-11 14:41:01 +05:30
}
expect ( Asciidoctor ) . to receive ( :convert )
. with ( input , expected_asciidoc_opts ) . and_return ( html )
2022-03-02 08:16:31 +05:30
render ( input , context )
2017-08-17 22:00:37 +05:30
end
2022-03-02 08:16:31 +05:30
end
2017-08-17 22:00:37 +05:30
2022-03-02 08:16:31 +05:30
context " with requested path " do
input = << ~ ADOC
Document name : { docname } .
ADOC
it " ignores {docname} when not available " do
expect ( render ( input , { } ) ) . to include ( input . strip )
end
[
[ '/' , '' , 'root' ] ,
[ 'README' , 'README' , 'just a filename' ] ,
[ 'doc/api/' , '' , 'a directory' ] ,
[ 'doc/api/README.adoc' , 'README' , 'a complete path' ]
] . each do | path , basename , desc |
it " sets {docname} for #{ desc } " do
expect ( render ( input , { requested_path : path } ) ) . to include ( " : #{ basename } . " )
end
end
end
2020-04-22 19:07:51 +05:30
2022-03-02 08:16:31 +05:30
context " XSS " do
items = {
'link with extra attribute' = > {
input : 'link:mylink"onmouseover="alert(1)[Click Here]' ,
output : " <div> \n <p><a href= \" mylink \" >Click Here</a></p> \n </div> "
} ,
'link with unsafe scheme' = > {
input : 'link:data://danger[Click Here]' ,
output : " <div> \n <p><a>Click Here</a></p> \n </div> "
} ,
'image with onerror' = > {
input : 'image:https://localhost.com/image.png[Alt text" onerror="alert(7)]' ,
2022-07-16 23:28:13 +05:30
output : " <div> \n <p><span><a class= \" no-attachment-icon \" href= \" https://localhost.com/image.png \" target= \" _blank \" rel= \" noopener noreferrer \" ><img src= \" data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== \" alt='Alt text \" onerror= \" alert(7)' decoding= \" async \" class= \" lazy \" data-src= \" https://localhost.com/image.png \" ></a></span></p> \n </div> "
2022-03-02 08:16:31 +05:30
}
}
2017-08-17 22:00:37 +05:30
2022-03-02 08:16:31 +05:30
items . each do | name , data |
it " does not convert dangerous #{ name } into HTML " do
expect ( render ( data [ :input ] , context ) ) . to include ( data [ :output ] )
2017-08-17 22:00:37 +05:30
end
end
2021-04-01 16:36:13 +05:30
2022-03-02 08:16:31 +05:30
# `stub_feature_flags method` runs AFTER declaration of `items` above.
# So the spec in its current implementation won't pass.
# Move this test back to the items hash when removing `use_cmark_renderer` feature flag.
it " does not convert dangerous fenced code with inline script into HTML " do
input = '```mypre"><script>alert(3)</script>'
output = " <div> \n <div> \n <div class= \" gl-relative markdown-code-block js-markdown-code \" > \n <pre class= \" code highlight js-syntax-highlight language-plaintext \" lang= \" plaintext \" v-pre= \" true \" ><code></code></pre> \n <copy-code></copy-code> \n </div> \n </div> \n </div> "
expect ( render ( input , context ) ) . to include ( output )
end
it 'does not allow locked attributes to be overridden' do
2021-04-01 16:36:13 +05:30
input = << ~ ADOC
2022-03-02 08:16:31 +05:30
{ counter : max - include - depth : 1234 }
< | - - { max - include - depth }
2021-04-01 16:36:13 +05:30
ADOC
2022-03-02 08:16:31 +05:30
expect ( render ( input , { } ) ) . not_to include ( '1234' )
end
end
2017-08-17 22:00:37 +05:30
2022-03-02 08:16:31 +05:30
context " images " do
it " does lazy load and link image " do
input = 'image:https://localhost.com/image.png[]'
2022-07-16 23:28:13 +05:30
output = " <div> \n <p><span><a class= \" no-attachment-icon \" href= \" https://localhost.com/image.png \" target= \" _blank \" rel= \" noopener noreferrer \" ><img src= \" data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== \" alt= \" image \" decoding= \" async \" class= \" lazy \" data-src= \" https://localhost.com/image.png \" ></a></span></p> \n </div> "
2022-03-02 08:16:31 +05:30
expect ( render ( input , context ) ) . to include ( output )
2019-12-26 22:10:19 +05:30
end
2022-03-02 08:16:31 +05:30
it " does not automatically link image if link is explicitly defined " do
input = 'image:https://localhost.com/image.png[link=https://gitlab.com]'
2022-07-16 23:28:13 +05:30
output = " <div> \n <p><span><a href= \" https://gitlab.com \" rel= \" nofollow noreferrer noopener \" target= \" _blank \" ><img src= \" data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== \" alt= \" image \" decoding= \" async \" class= \" lazy \" data-src= \" https://localhost.com/image.png \" ></a></span></p> \n </div> "
2022-03-02 08:16:31 +05:30
expect ( render ( input , context ) ) . to include ( output )
end
end
2019-12-26 22:10:19 +05:30
2022-03-02 08:16:31 +05:30
context 'with admonition' do
it 'preserves classes' do
input = << ~ ADOC
NOTE : An admonition paragraph , like this note , grabs the reader ’ s attention .
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div class = " admonitionblock " >
< table >
< tr >
< td class = " icon " >
< i class = " fa icon-note " title = " Note " > < / i>
< / td>
< td >
An admonition paragraph , like this note , grabs the reader ’ s attention .
< / td>
< / tr>
< / table>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
end
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with passthrough' do
it 'removes non heading ids' do
input = << ~ ADOC
+ + + +
< h2 id = " foo " > Title < / h2>
+ + + +
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< h2 > Title < / h2>
HTML
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
it 'removes non footnote def ids' do
input = << ~ ADOC
+ + + +
< div id = " def " > Footnote definition < / div>
+ + + +
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div > Footnote definition < / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
it 'removes non footnote ref ids' do
input = << ~ ADOC
+ + + +
< a id = " ref " > Footnote reference < / a>
+ + + +
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< a > Footnote reference < / a>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with footnotes' do
it 'preserves ids and links' do
input = << ~ ADOC
This paragraph has a footnote . footnote : [ This is the text of the footnote . ]
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< p > This paragraph has a footnote . < sup > [ < a id = " _footnoteref_1 " href = " # _footnotedef_1 " title = " View footnote. " > 1 < / a>]< /su p > < / p>
< / div>
< div >
< hr >
< div id = " _footnotedef_1 " >
< a href = " # _footnoteref_1 " > 1 < / a>. This is the text of the footnote.
< / div>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
end
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with section anchors' do
it 'preserves ids and links' do
input = << ~ ADOC
= Title
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
== First section
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
This is the first section .
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
== Second section
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
This is the second section .
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
== Thunder ⚡ !
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
This is the third section .
ADOC
output = << ~ HTML
< h1 > Title < / h1>
< div >
< h2 id = " user-content-first-section " >
< a class = " anchor " href = " # user-content-first-section " > < / a>First section< / h2 >
< div >
< div >
< p > This is the first section . < / p>
< / div>
< / div>
< / div>
< div >
< h2 id = " user-content-second-section " >
< a class = " anchor " href = " # user-content-second-section " > < / a>Second section< / h2 >
< div >
< div >
< p > This is the second section . < / p>
< / div>
< / div>
< / div>
< div >
< h2 id = " user-content-thunder " >
< a class = " anchor " href = " # user-content-thunder " > < / a>Thunder ⚡ !< / h2 >
< div >
< div >
< p > This is the third section . < / p>
< / div>
< / div>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2021-02-22 17:27:13 +05:30
2022-03-02 08:16:31 +05:30
context 'with xrefs' do
it 'preserves ids' do
input = << ~ ADOC
Learn how to xref : cross - references [ use cross references ] .
2021-02-22 17:27:13 +05:30
2022-03-02 08:16:31 +05:30
[ [ cross - references ] ] A link to another location within an AsciiDoc document or between AsciiDoc documents is called a cross reference ( also referred to as an xref ) .
ADOC
output = << ~ HTML
< div >
< p > Learn how to < a href = " # cross-references " > use cross references < / a>.< / p >
< / div>
< div >
< p > < a id = " user-content-cross-references " > < / a>A link to another location within an AsciiDoc document or between AsciiDoc documents is called a cross reference (also referred to as an xref).< / p >
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2021-02-22 17:27:13 +05:30
end
2022-03-02 08:16:31 +05:30
end
2021-02-22 17:27:13 +05:30
2022-03-02 08:16:31 +05:30
context 'with checklist' do
it 'preserves classes' do
input = << ~ ADOC
* [ x ] checked
* [ ] not checked
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< ul class = " checklist " >
< li >
< p > < i class = " fa fa-check-square-o " > < / i> checked< / p >
< / li>
< li >
< p > < i class = " fa fa-square-o " > < / i> not checked< / p >
< / li>
< / ul>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with marks' do
it 'preserves classes' do
input = << ~ ADOC
Werewolves are allergic to #cassia cinnamon#.
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
Did the werewolves read the [ . small ] #small print#?
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
Where did all the [ . underline . small ] #cores# run off to?
We need [ . line - through ] #ten# make that twenty VMs.
[ . big ] ##O##nce upon an infinite loop.
ADOC
output = << ~ HTML
< div >
< p > Werewolves are allergic to < mark > cassia cinnamon < / mark>.< / p >
< / div>
< div >
< p > Did the werewolves read the < span class = " small " > small print < / span>?< / p >
< / div>
< div >
< p > Where did all the < span class = " underline small " > cores < / span> run off to?< / p >
< / div>
< div >
< p > We need < span class = " line-through " > ten < / span> make that twenty VMs.< / p >
< / div>
< div >
< p > < span class = " big " > O < / span>nce upon an infinite loop.< / p >
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with fenced block' do
it 'highlights syntax' do
input = << ~ ADOC
` ` ` js
console . log ( 'hello world' )
` ` `
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< div >
< div class = " gl-relative markdown-code-block js-markdown-code " >
< pre class = " code highlight js-syntax-highlight language-javascript " lang = " javascript " v - pre = " true " > < code > < span id = " LC1 " class = " line " lang = " javascript " > < span class = " nx " > console < / span><span class="p">.< /s pan > < span class = " nx " > log < / span><span class="p">(< /s pan > < span class = " dl " > '</span><span class="s1">hello world</span><span class="dl">' < / span><span class="p">)< /s pan > < / span>< / code > < / pre>
< copy - code > < / copy-code>
< / div>
< / div>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with listing block' do
it 'highlights syntax' do
input = << ~ ADOC
[ source , c + + ]
. class . cpp
- - - -
#include <stdio.h>
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
for ( int i = 0 ; i < 5 ; i + + ) {
std :: cout << " * " <<std::endl;
}
- - - -
ADOC
output = << ~ HTML
< div >
< div > class . cpp < / div>
< div >
< div class = " gl-relative markdown-code-block js-markdown-code " >
< pre class = " code highlight js-syntax-highlight language-cpp " lang = " cpp " v - pre = " true " > < code > < span id = " LC1 " class = " line " lang = " cpp " > < span class = " cp " > #include <stdio.h></span></span>
< span id = " LC2 " class = " line " lang = " cpp " > < / span>
< span id = " LC3 " class = " line " lang = " cpp " > < span class = " k " > for < / span> <span class="p">(< /s pan > < span class = " kt " > int < / span> <span class="n">i< /s pan > < span class = " o " > = < / span> <span class="mi">0< /s pan > < span class = " p " > ; < / span> <span class="n">i< /s pan > < span class = " o " > & lt ; < / span> <span class="mi">5< /s pan > < span class = " p " > ; < / span> <span class="n">i< /s pan > < span class = " o " > + + < / span><span class="p">)< /s pan > < span class = " p " > { < / span>< /s pan >
< span id = " LC4 " class = " line " lang = " cpp " > < span class = " n " > std < / span><span class="o">::< /s pan > < span class = " n " > cout < / span><span class="o"><<< /s pan > < span class = " s " > " * " < / span><span class="o"><<< /s pan > < span class = " n " > std < / span><span class="o">::< /s pan > < span class = " n " > endl < / span><span class="p">;< /s pan > < / span>
< span id = " LC5 " class = " line " lang = " cpp " > < span class = " p " > } < / span>< /s pan > < / code>< / pre >
< copy - code > < / copy-code>
< / div>
< / div>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'with stem block' do
it 'does not apply syntax highlighting' do
input = << ~ ADOC
[ stem ]
+ + + +
\ sqrt { 4 } = 2
+ + + +
ADOC
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
output = " <div> \n <div> \n \\ $ qrt{4} = 2 \\ $ \n </div> \n </div> "
expect ( render ( input , context ) ) . to include ( output )
2019-09-30 21:07:59 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-30 21:07:59 +05:30
2022-03-02 08:16:31 +05:30
context 'external links' do
it 'adds the `rel` attribute to the link' do
output = render ( 'link:https://google.com[Google]' , context )
2017-08-17 22:00:37 +05:30
2022-03-02 08:16:31 +05:30
expect ( output ) . to include ( 'rel="nofollow noreferrer noopener"' )
2015-09-11 14:41:01 +05:30
end
2022-03-02 08:16:31 +05:30
end
2017-09-10 17:25:29 +05:30
2022-03-02 08:16:31 +05:30
context 'LaTex code' do
it 'adds class js-render-math to the output' do
input = << ~ MD
:stem : latexmath
2017-09-10 17:25:29 +05:30
2022-03-02 08:16:31 +05:30
[ stem ]
+ + + +
\ sqrt { 4 } = 2
+ + + +
2017-09-10 17:25:29 +05:30
2022-03-02 08:16:31 +05:30
another part
[ latexmath ]
+ + + +
\ beta_x \ gamma
+ + + +
stem : [ 2 + 2 ] is 4
MD
expect ( render ( input , context ) ) . to include ( '<pre data-math-style="display" class="code math js-render-math"><code>eta_x gamma</code></pre>' )
expect ( render ( input , context ) ) . to include ( '<p><code data-math-style="inline" class="code math js-render-math">2+2</code> is 4</p>' )
2017-09-10 17:25:29 +05:30
end
2022-03-02 08:16:31 +05:30
end
2018-03-27 19:54:05 +05:30
2022-03-02 08:16:31 +05:30
context 'outfilesuffix' do
it 'defaults to adoc' do
output = render ( " Inter-document reference <<README.adoc # >> " , context )
2018-03-27 19:54:05 +05:30
2022-03-02 08:16:31 +05:30
expect ( output ) . to include ( " a href= \" README.adoc \" " )
2018-03-27 19:54:05 +05:30
end
2022-03-02 08:16:31 +05:30
end
2020-10-24 23:57:45 +05:30
2022-03-02 08:16:31 +05:30
context 'with mermaid diagrams' do
it 'adds class js-render-mermaid to the output' do
input = << ~ MD
[ mermaid ]
... .
graph LR
A [ Square Rect ] - - Link text - - > B ( ( Circle ) )
A - - > C ( Round Rect )
B - - > D { Rhombus }
C - - > D
... .
MD
output = << ~ HTML
< pre data - mermaid - style = " display " class = " js-render-mermaid " > graph LR
A [ Square Rect ] - - Link text - - & gt ; B ( ( Circle ) )
A - - & gt ; C ( Round Rect )
B - - & gt ; D { Rhombus }
C - - & gt ; D < / pre>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
2020-10-24 23:57:45 +05:30
end
2022-03-02 08:16:31 +05:30
it 'applies subs in diagram block' do
input = << ~ MD
:class - name : AveryLongClass
2020-10-24 23:57:45 +05:30
2022-03-02 08:16:31 +05:30
[ mermaid , subs = + attributes ]
... .
classDiagram
Class01 < | - - { class - name } : Cool
... .
MD
2020-10-24 23:57:45 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< pre data - mermaid - style = " display " class = " js-render-mermaid " > classDiagram
Class01 & lt ; | - - AveryLongClass : Cool < / pre>
HTML
2020-10-24 23:57:45 +05:30
2022-03-02 08:16:31 +05:30
expect ( render ( input , context ) ) . to include ( output . strip )
2020-10-24 23:57:45 +05:30
end
2022-03-02 08:16:31 +05:30
end
2021-02-22 17:27:13 +05:30
2022-03-02 08:16:31 +05:30
context 'with Kroki enabled' do
before do
allow_any_instance_of ( ApplicationSetting ) . to receive ( :kroki_enabled ) . and_return ( true )
allow_any_instance_of ( ApplicationSetting ) . to receive ( :kroki_url ) . and_return ( 'https://kroki.io' )
end
2021-02-22 17:27:13 +05:30
2022-03-02 08:16:31 +05:30
it 'converts a graphviz diagram to image' do
input = << ~ ADOC
[ graphviz ]
... .
digraph G {
Hello - > World
}
... .
ADOC
2021-02-22 17:27:13 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< div >
2022-07-16 23:28:13 +05:30
< a class = " no-attachment-icon " href = " https://kroki.io/graphviz/svg/eNpLyUwvSizIUHBXqOZSUPBIzcnJ17ULzy_KSeGqBQCEzQka " target = " _blank " rel = " noopener noreferrer " > < img src = " data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== " alt = " Diagram " decoding = " async " class = " lazy " data - src = " https://kroki.io/graphviz/svg/eNpLyUwvSizIUHBXqOZSUPBIzcnJ17ULzy_KSeGqBQCEzQka " > < / a>
2022-03-02 08:16:31 +05:30
< / div>
< / div>
HTML
2021-03-11 19:13:27 +05:30
2022-03-02 08:16:31 +05:30
expect ( render ( input , context ) ) . to include ( output . strip )
end
2021-03-11 19:13:27 +05:30
2022-03-02 08:16:31 +05:30
it 'does not convert a blockdiag diagram to image' do
input = << ~ ADOC
[ blockdiag ]
... .
blockdiag {
Kroki - > generates - > " Block diagrams " ;
Kroki - > is - > " very easy! " ;
Kroki [ color = " greenyellow " ] ;
" Block diagrams " [ color = " pink " ] ;
" very easy! " [ color = " orange " ] ;
}
... .
ADOC
2021-04-01 16:36:13 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< div >
< pre > blockdiag {
Kroki - & gt ; generates - & gt ; " Block diagrams " ;
Kroki - & gt ; is - & gt ; " very easy! " ;
Kroki [ color = " greenyellow " ] ;
" Block diagrams " [ color = " pink " ] ;
" very easy! " [ color = " orange " ] ;
} < / pre>
< / div>
< / div>
HTML
expect ( render ( input , context ) ) . to include ( output . strip )
end
2021-04-01 16:36:13 +05:30
2022-03-02 08:16:31 +05:30
it 'does not allow kroki-plantuml-include to be overridden' do
input = << ~ ADOC
[ plantuml , test = " {counter:kroki-plantuml-include:/etc/passwd} " , format = " png " ]
... .
class BlockProcessor
2021-12-11 22:18:48 +05:30
2022-03-02 08:16:31 +05:30
BlockProcessor < | - - { counter : kroki - plantuml - include }
... .
ADOC
2021-04-01 16:36:13 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< div >
2022-07-16 23:28:13 +05:30
< a class = \ " no-attachment-icon \" href= \" https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A== \" target= \" _blank \" rel= \" noopener noreferrer \" ><img src= \" data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== \" alt= \" Diagram \" decoding= \" async \" class= \" lazy \" data-src= \" https://kroki.io/plantuml/png/eNpLzkksLlZwyslPzg4oyk9OLS7OL-LiQuUr2NTo6ipUJ-eX5pWkFlllF-VnZ-oW5CTmlZTm5uhm5iXnlKak1gIABQEb8A== \" ></a>
2022-03-02 08:16:31 +05:30
< / div>
< / div>
HTML
2021-04-01 16:36:13 +05:30
2022-03-02 08:16:31 +05:30
expect ( render ( input , { } ) ) . to include ( output . strip )
2021-04-01 16:36:13 +05:30
end
2022-03-02 08:16:31 +05:30
it 'does not allow kroki-server-url to be overridden' do
input = << ~ ADOC
[ plantuml , test = " {counter:kroki-server-url:evilsite} " , format = " png " ]
... .
class BlockProcessor
2021-04-01 16:36:13 +05:30
2022-03-02 08:16:31 +05:30
BlockProcessor
... .
ADOC
2021-12-11 22:18:48 +05:30
2022-03-02 08:16:31 +05:30
expect ( render ( input , { } ) ) . not_to include ( 'evilsite' )
2021-04-01 16:36:13 +05:30
end
2021-03-11 19:13:27 +05:30
end
2022-03-02 08:16:31 +05:30
context 'with Kroki and BlockDiag (additional format) enabled' do
before do
allow_any_instance_of ( ApplicationSetting ) . to receive ( :kroki_enabled ) . and_return ( true )
allow_any_instance_of ( ApplicationSetting ) . to receive ( :kroki_url ) . and_return ( 'https://kroki.io' )
allow_any_instance_of ( ApplicationSetting ) . to receive ( :kroki_formats_blockdiag ) . and_return ( true )
2021-03-11 19:13:27 +05:30
end
2022-03-02 08:16:31 +05:30
it 'converts a blockdiag diagram to image' do
input = << ~ ADOC
[ blockdiag ]
... .
blockdiag {
Kroki - > generates - > " Block diagrams " ;
Kroki - > is - > " very easy! " ;
Kroki [ color = " greenyellow " ] ;
" Block diagrams " [ color = " pink " ] ;
" very easy! " [ color = " orange " ] ;
}
... .
ADOC
2021-03-11 19:13:27 +05:30
2022-03-02 08:16:31 +05:30
output = << ~ HTML
< div >
< div >
2022-07-16 23:28:13 +05:30
< a class = " no-attachment-icon " href = " https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w== " target = " _blank " rel = " noopener noreferrer " > < img src = " data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== " alt = " Diagram " decoding = " async " class = " lazy " data - src = " https://kroki.io/blockdiag/svg/eNpdzDEKQjEQhOHeU4zpPYFoYesRxGJ9bwghMSsbUYJ4d10UCZbDfPynolOek0Q8FsDeNCestoisNLmy-Qg7R3Blcm5hPcr0ITdaB6X15fv-_YdJixo2CNHI2lmK3sPRA__RwV5SzV80ZAegJjXSyfMFptc71w== " > < / a>
2022-03-02 08:16:31 +05:30
< / div>
< / div>
HTML
2015-09-11 14:41:01 +05:30
2022-03-02 08:16:31 +05:30
expect ( render ( input , context ) ) . to include ( output . strip )
end
end
end
2020-10-24 23:57:45 +05:30
2022-03-02 08:16:31 +05:30
context 'with project' do
let ( :context ) do
{
commit : commit ,
project : project ,
ref : ref ,
requested_path : requested_path
}
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
let ( :commit ) { project . commit ( ref ) }
let ( :project ) { create ( :project , :repository ) }
let ( :ref ) { 'asciidoc' }
let ( :requested_path ) { '/' }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'include directive' do
subject ( :output ) { render ( input , context ) }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
let ( :input ) { " Include this: \n \n include:: #{ include_path } [] " }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
before do
current_file = requested_path
current_file += 'README.adoc' if requested_path . end_with? '/'
2020-02-01 01:16:34 +05:30
2022-03-02 08:16:31 +05:30
create_file ( current_file , " = AsciiDoc \n " )
end
def many_includes ( target )
Array . new ( 10 , " include:: #{ target } [] " ) . join ( " \n " )
end
context 'cyclic imports' do
before do
create_file ( 'doc/api/a.adoc' , many_includes ( 'b.adoc' ) )
create_file ( 'doc/api/b.adoc' , many_includes ( 'a.adoc' ) )
2020-02-01 01:16:34 +05:30
end
2022-03-02 08:16:31 +05:30
let ( :include_path ) { 'a.adoc' }
let ( :requested_path ) { 'doc/api/README.md' }
2020-02-01 01:16:34 +05:30
2022-03-02 08:16:31 +05:30
it 'completes successfully' do
is_expected . to include ( '<p>Include this:</p>' )
2020-02-01 01:16:34 +05:30
end
2022-03-02 08:16:31 +05:30
end
2020-02-01 01:16:34 +05:30
2022-03-02 08:16:31 +05:30
context 'with path to non-existing file' do
let ( :include_path ) { 'not-exists.adoc' }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
it 'renders Unresolved directive placeholder' do
is_expected . to include ( " <strong>[ERROR: include:: #{ include_path } [] - unresolved directive]</strong> " )
end
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
shared_examples :invalid_include do
let ( :include_path ) { 'dk.png' }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
before do
allow ( project . repository ) . to receive ( :blob_at ) . and_return ( blob )
2019-09-04 21:01:54 +05:30
end
2022-03-02 08:16:31 +05:30
it 'does not read the blob' do
expect ( blob ) . not_to receive ( :data )
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
it 'renders Unresolved directive placeholder' do
is_expected . to include ( " <strong>[ERROR: include:: #{ include_path } [] - unresolved directive]</strong> " )
2019-09-04 21:01:54 +05:30
end
2022-03-02 08:16:31 +05:30
end
2020-01-01 13:55:28 +05:30
2022-03-02 08:16:31 +05:30
context 'with path to a binary file' do
let ( :blob ) { fake_blob ( path : 'dk.png' , binary : true ) }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
include_examples :invalid_include
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'with path to file in external storage' do
let ( :blob ) { fake_blob ( path : 'dk.png' , lfs : true ) }
before do
allow ( Gitlab . config . lfs ) . to receive ( :enabled ) . and_return ( true )
project . update_attribute ( :lfs_enabled , true )
2019-09-04 21:01:54 +05:30
end
2022-03-02 08:16:31 +05:30
include_examples :invalid_include
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'with path to a textual file' do
let ( :include_path ) { 'sample.adoc' }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
before do
create_file ( file_path , " Content from #{ include_path } " )
end
shared_examples :valid_include do
[
[ '/doc/sample.adoc' , 'doc/sample.adoc' , 'absolute path' ] ,
[ 'sample.adoc' , 'doc/api/sample.adoc' , 'relative path' ] ,
[ './sample.adoc' , 'doc/api/sample.adoc' , 'relative path with leading ./' ] ,
[ '../sample.adoc' , 'doc/sample.adoc' , 'relative path to a file up one directory' ] ,
[ '../../sample.adoc' , 'sample.adoc' , 'relative path for a file up multiple directories' ]
] . each do | include_path_ , file_path_ , desc |
context " the file is specified by #{ desc } " do
let ( :include_path ) { include_path_ }
let ( :file_path ) { file_path_ }
it 'includes content of the file' do
is_expected . to include ( '<p>Include this:</p>' )
is_expected . to include ( " <p>Content from #{ include_path } </p> " )
2019-09-04 21:01:54 +05:30
end
end
end
2022-03-02 08:16:31 +05:30
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'when requested path is a file in the repo' do
let ( :requested_path ) { 'doc/api/README.adoc' }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
include_examples :valid_include
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'without a commit (only ref)' do
let ( :commit ) { nil }
2020-01-01 13:55:28 +05:30
2022-03-02 08:16:31 +05:30
include_examples :valid_include
2019-09-04 21:01:54 +05:30
end
2022-03-02 08:16:31 +05:30
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'when requested path is a directory in the repo' do
let ( :requested_path ) { 'doc/api/' }
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
include_examples :valid_include
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'without a commit (only ref)' do
let ( :commit ) { nil }
2020-01-01 13:55:28 +05:30
2022-03-02 08:16:31 +05:30
include_examples :valid_include
2019-09-04 21:01:54 +05:30
end
end
2022-03-02 08:16:31 +05:30
end
2020-03-13 15:44:24 +05:30
2022-03-02 08:16:31 +05:30
context 'when repository is passed into the context' do
let ( :wiki_repo ) { project . wiki . repository }
let ( :include_path ) { 'wiki_file.adoc' }
2020-03-13 15:44:24 +05:30
2022-03-02 08:16:31 +05:30
before do
project . create_wiki
context . merge! ( repository : wiki_repo )
end
context 'when the file exists' do
2020-03-13 15:44:24 +05:30
before do
2022-03-02 08:16:31 +05:30
create_file ( include_path , 'Content from wiki' , repository : wiki_repo )
2020-03-13 15:44:24 +05:30
end
2022-03-02 08:16:31 +05:30
it { is_expected . to include ( '<p>Content from wiki</p>' ) }
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'when the file does not exist' do
it { is_expected . to include ( " [ERROR: include:: #{ include_path } [] - unresolved directive] " ) }
end
end
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
context 'recursive includes with relative paths' do
let ( :input ) do
<< ~ ADOC
Source : requested file
include :: doc / README . adoc [ ]
include :: license . adoc [ ]
ADOC
2019-09-04 21:01:54 +05:30
end
2022-03-02 08:16:31 +05:30
before do
create_file 'doc/README.adoc' , << ~ ADOC
Source : doc / README . adoc
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
include :: .. / license . adoc [ ]
2019-09-04 21:01:54 +05:30
2022-03-02 08:16:31 +05:30
include :: api / hello . adoc [ ]
ADOC
create_file 'license.adoc' , << ~ ADOC
Source : license . adoc
ADOC
create_file 'doc/api/hello.adoc' , << ~ ADOC
Source : doc / api / hello . adoc
include :: . / common . adoc [ ]
ADOC
create_file 'doc/api/common.adoc' , << ~ ADOC
Source : doc / api / common . adoc
ADOC
2019-09-04 21:01:54 +05:30
end
2022-03-02 08:16:31 +05:30
it 'includes content of the included files recursively' do
expect ( output . gsub ( / <[^>]+> / , '' ) . gsub ( / \ n \ s* / , " \n " ) . strip ) . to eq << ~ ADOC . strip
Source : requested file
Source : doc / README . adoc
Source : license . adoc
Source : doc / api / hello . adoc
Source : doc / api / common . adoc
Source : license . adoc
ADOC
2019-09-04 21:01:54 +05:30
end
end
2022-03-02 08:16:31 +05:30
def create_file ( path , content , repository : project . repository )
repository . create_file ( project . creator , path , content ,
message : " Add #{ path } " , branch_name : 'asciidoc' )
end
2019-09-04 21:01:54 +05:30
end
end
2015-09-11 14:41:01 +05:30
def render ( * args )
described_class . render ( * args )
end
end
end