Commit d64f6011 authored by Gabriel Mazetto's avatar Gabriel Mazetto

Merge branch 'bw-jira-markdown-2' into 'master'

Create pipeline/filter converting Atlassian Document Format to GFM

See merge request gitlab-org/gitlab!32362
parents 4c464c81 4292a286
...@@ -140,6 +140,7 @@ gem 'deckar01-task_list', '2.3.1' ...@@ -140,6 +140,7 @@ gem 'deckar01-task_list', '2.3.1'
gem 'gitlab-markup', '~> 1.7.1' gem 'gitlab-markup', '~> 1.7.1'
gem 'github-markup', '~> 1.7.0', require: 'github/markup' gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'commonmarker', '~> 0.20' gem 'commonmarker', '~> 0.20'
gem 'kramdown', '~> 2.2.1'
gem 'RedCloth', '~> 4.3.2' gem 'RedCloth', '~> 4.3.2'
gem 'rdoc', '~> 6.1.2' gem 'rdoc', '~> 6.1.2'
gem 'org-ruby', '~> 0.9.12' gem 'org-ruby', '~> 0.9.12'
......
...@@ -575,7 +575,8 @@ GEM ...@@ -575,7 +575,8 @@ GEM
kgio (2.11.3) kgio (2.11.3)
knapsack (1.17.0) knapsack (1.17.0)
rake rake
kramdown (2.1.0) kramdown (2.2.1)
rexml
kramdown-parser-gfm (1.1.0) kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0) kramdown (~> 2.0)
kubeclient (4.6.0) kubeclient (4.6.0)
...@@ -1282,6 +1283,7 @@ DEPENDENCIES ...@@ -1282,6 +1283,7 @@ DEPENDENCIES
jwt (~> 2.1.0) jwt (~> 2.1.0)
kaminari (~> 1.0) kaminari (~> 1.0)
knapsack (~> 1.17) knapsack (~> 1.17)
kramdown (~> 2.2.1)
kubeclient (~> 4.6.0) kubeclient (~> 4.6.0)
letter_opener_web (~> 1.3.4) letter_opener_web (~> 1.3.4)
license_finder (~> 5.4) license_finder (~> 5.4)
......
# frozen_string_literal: true
module Banzai
module Filter
module JiraImport
# Uses Kramdown to convert from the Atlassian Document Format (json)
# into CommonMark
# @see https://developer.atlassian.com/cloud/jira/platform/apis/document/structure/
class AdfToCommonmarkFilter < HTML::Pipeline::TextFilter
def initialize(text, context = nil, result = nil)
super(text, context, result)
end
def call
Kramdown::Document.new(@text, input: 'AtlassianDocumentFormat', html_tables: true).to_commonmark
rescue ::Kramdown::Error => e
# If we get an error, then just return the original text so at
# least the user knows something went wrong
"#{e.message}\n\n#{@text}"
end
end
end
end
end
# frozen_string_literal: true
module Banzai
module Pipeline
module JiraImport
class AdfCommonmarkPipeline < BasePipeline
def self.filters
FilterArray[
Filter::JiraImport::AdfToCommonmarkFilter
]
end
end
end
end
end
# frozen_string_literal: true
module Kramdown
module Converter
# Overrides the base Kramdown converter to add any special
# behaviour for CommonMark.
#
# Currently we support an option `html_tables` that outputs
# an HTML table instead of a Markdown table. This is to
# support possibly being given complex tables, such as from ADF.
#
# Note: this is only an initial implementation. Currently don't
# strip out IALs or other specific kramdown syntax.
class Commonmark < ::Kramdown::Converter::Kramdown
def convert_table(el, opts)
return super unless @options[:html_tables]
opts[:alignment] = el.options[:alignment]
result = inner(el, opts)
"<table>\n#{result}</table>\n\n"
end
def convert_thead(el, opts)
return super unless @options[:html_tables]
"<thead>\n#{inner(el, opts)}</thead>\n"
end
def convert_tbody(el, opts)
return super unless @options[:html_tables]
"<tbody>\n#{inner(el, opts)}</tbody>\n"
end
def convert_tfoot(el, opts)
return super unless @options[:html_tables]
"<tfoot>\n#{inner(el, opts)}</tfoot>\n"
end
def convert_tr(el, opts)
return super unless @options[:html_tables]
"<tr>\n#{el.children.map {|c| convert(c, opts) }.join}</tr>\n"
end
def convert_td(el, opts)
return super unless @options[:html_tables]
# We need to add two linefeeds in order for any inner text to
# be processed as markdown. The HTML block must be "closed",
# as referenced in the CommonMark spec
# @see https://spec.commonmark.org/0.29/#html-blocks
"<td>\n\n#{inner(el, opts)}</td>\n"
end
def convert_th(el, opts)
return super unless @options[:html_tables]
# We need to add two linefeeds in order for any inner text to
# be processed as markdown. The HTML block must be "closed",
# as referenced in the CommonMark spec
# @see https://spec.commonmark.org/0.29/#html-blocks
"<th>\n\n#{inner(el, opts)}</th>\n"
end
end
end
end
This diff is collapsed.
{
"version": 1,
"type": "doc",
"content": [
{
"type": "blockquote",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a sample quote"
},
{
"type": "text",
"text": " with lorem ipsum dolor sit amet..."
}
]
}
]
}
]
}
> This is a sample quote with lorem ipsum dolor sit amet...
{
"version": 1,
"type": "doc",
"content": [
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Item 1"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Item 2",
"marks": [
{
"type": "strong"
}
]
}
]
},
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Sub-item 1"
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Sub-item 1 paragraph"
}
]
}
]
}
]
}
]
}
]
}
]
}
* Item 1
* **Item 2**
* Sub-item 1
Sub-item 1 paragraph
{
"version": 1,
"type": "doc",
"content": [
{
"type": "codeBlock",
"attrs": {
"language": "javascript"
},
"content": [
{
"type": "text",
"text": "export function makeIssue({ parentIssue, project, users }) {\n\n const issueType = pickRandom(project.issueTypes)\n\n console.log(data)\n\n return data\n}"
}
]
},
{
"type": "bulletList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Item 1"
}
]
},
{
"type": "codeBlock",
"content": [
{
"type": "text",
"text": "public DemoClass()\n{\n // assign default value\n x = 0;\n}"
}
]
}
]
}
]
}
]
}
export function makeIssue({ parentIssue, project, users }) {
const issueType = pickRandom(project.issueTypes)
console.log(data)
return data
}
* Item 1
public DemoClass()
{
// assign default value
x = 0;
}
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is some "
},
{
"type": "text",
"text": "inline code",
"marks": [
{
"type": "code"
}
]
}
]
}
]
}
This is a complex issue…and this is normal text
* * *
Color - Dark Gray
Color - <span color="#97a0af">Light Gray</span>
Color - <span color="#6554c0">Purple</span>
Color - <span color="#00b8d9">Teal</span>
Color - <span color="#36b37e">Green</span>
Color - <span color="#ff5630">Red</span>
Color - <span color="#ff991f">Orange</span>
* * *
[https://gitlab-jira.atlassian.net/browse/DEMO-1][1]
`adf-inlineCard:
{"@context"=>"https://json-ld.org/contexts/person.jsonld",
"@id"=>"http://dbpedia.org/resource/John_Lennon", "name"=>"John Lennon",
"born"=>"1940-10-09",
"spouse"=>"http://dbpedia.org/resource/Cynthia_Lennon"}`
[External Link][2]
* * *
> This is a block quote
> \:white\_check\_mark: Success info panel
> \:information\_source: Info info panel
> \:notepad\_spiral: Note info panel
> \:warning: Warning info panel
> \:octagonal\_sign: Error info panel
* * *
@adf-mention:jhope what up
😀 🤣 🥳 😍
<table>
<tbody>
<tr>
<th>
**Col 1 Row 1**
</th>
<th>
**Col 2 Row 1**
</th>
<th>
**Col 3 Row 1**
</th>
</tr>
<tr>
<td>
Col 1 Row 2
</td>
<td>
Col 2 Row 2
</td>
<td>
Col 3 Row 2
</td>
</tr>
<tr>
<td>
Col 1 Row 3
</td>
<td>
Col 2 Row 3
</td>
<td>
Col 3 Row 3
</td>
</tr>
</tbody>
</table>
# Header 1
## Header 2
### Header 3
#### Header 4
##### Header 5
###### Header 6
* Bullet point list item 1
* Bullet point list Item 2
* Bullet point list Item 3
1. Number list Item 1
2. Number list item 2
3. Number list item 3
<u>Underline</u>
<sup>Superscript</sup>
<sub>Subscript</sub>
**Bold**
*Italic*
<del>Strikethrough</del>
export function makeIssue({ parentIssue, project, users }) {
const issueType = pickRandom(project.issueTypes)
let data = {
fields: {
summary: faker.lorem.sentence(),
issuetype: {
id: issueType.id
},
project: {
id: project.id
},
reporter: {
id: pickRandom(users)
}
}
}
if (issueType.subtask) {
data = {
parent: {
key: parentIssue
}
}
}
console.log(data)
return data
}
![jira-10050-field-description](adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c)
![jira-10050-field-description](adf-media://6a5b48c6-70bd-4747-9ac8-a9abc9adb1f4)
![jira-10050-field-description](adf-media://e818a88d-9185-4a7f-8882-18339a0f0966)
blob:[https://gitlab-jira.atlassian.net/5eb8e93b-7b15-446f-82d9-9d82ad7b8ea5#media-blob-url=true&id=572b2c1b-1b38-44ba-904a-649ee1861917&collection=upload-user-collection-426749591&contextId=10042&mimeType=image%2Fpng&name=import-jira-issues.png&size=294408][3]
[1]: https://gitlab-jira.atlassian.net/browse/DEMO-1
[2]: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25718
[3]: https://gitlab-jira.atlassian.net/5eb8e93b-7b15-446f-82d9-9d82ad7b8ea5#media-blob-url=true&id=572b2c1b-1b38-44ba-904a-649ee1861917&collection=upload-user-collection-426749591&contextId=10042&mimeType=image%2Fpng&name=import-jira-issues.png&size=294408
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Grinning with unicode "
},
{
"type": "emoji",
"attrs": {
"shortName": ":grinning:",
"text": "😀"
}
},
{
"type": "text",
"text": " and heart eyes with raw unicode "
},
{
"type": "emoji",
"attrs": {
"shortName": ":heart_eyes:",
"id": "1f60d",
"text": "\uD83D\uDE0D"
}
},
{
"type": "text",
"text": ", non-standard Atlassian "
},
{
"type": "emoji",
"attrs": {
"shortName": ":awthanks:",
"id": "atlassian-awthanks",
"text": ":awthanks:"
}
},
{
"type": "text",
"text": ", non-standard customer emoji "
},
{
"type": "emoji",
"attrs": {
"shortName": ":thumbsup::skin-tone-2:"
}
},
{
"type": "text",
"text": ", and invalid is ignored "
},
{
"type": "emoji",
"attrs": {
"id": "1f44d"
}
}
]
}
]
}
Grinning with unicode 😀 and heart eyes with raw unicode 😍, non-standard
Atlassian :awthanks:, non-standard customer emoji
:thumbsup::skin-tone-2:, and invalid is ignored
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a sample paragraph"
},
{
"type": "hardBreak"
},
{
"type": "text",
"text": "with lorem ipsum dolor sit amet..."
}
]
}
]
}
This is a sample paragraph
with lorem ipsum dolor sit amet...
{
"version": 1,
"type": "doc",
"content": [
{
"type": "heading",
"attrs": {
"level": 1
},
"content": [
{
"type": "text",
"text": "Header 1"
}
]
},
{
"type": "heading",
"attrs": {
"level": 2
},
"content": [
{
"type": "text",
"text": "Header 2",
"marks": [
{
"type": "strong"
}
]
}
]
},
{
"type": "heading",
"attrs": {
"level": 3
},
"content": [
{
"type": "text",
"text": "Header 3"
}
]
},
{
"type": "heading",
"attrs": {
"level": 4
},
"content": [
{
"type": "text",
"text": "Header 4",
"marks": [
{
"type": "textColor",
"attrs": {
"color": "#ff6347"
}
}
]
}
]
},
{
"type": "heading",
"attrs": {
"level": 5
},
"content": [
{
"type": "text",
"text": "Header 5"
}
]
},
{
"type": "heading",
"attrs": {
"level": 6
},
"content": [
{
"type": "text",
"text": "Header 6"
}
]
}
]
}
# Header 1
## **Header 2**
### Header 3
#### <span color="#ff6347">Header 4</span>
##### Header 5
###### Header 6
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "An inline card (url): "
},
{
"type": "inlineCard",
"attrs": {
"url": "https://gitlab-jira.atlassian.net/browse/DEMO-1"
}
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Some prelude text "
},
{
"type": "inlineCard",
"attrs": {
"data": {
"@context": "https://json-ld.org/contexts/person.jsonld",
"@id": "http://dbpedia.org/resource/John_Lennon",
"name": "John Lennon",
"born": "1940-10-09",
"spouse": "http://dbpedia.org/resource/Cynthia_Lennon"
}
}
},
{
"type": "text",
"text": " some following text"
}
]
}
]
}
An inline card (url):
[https://gitlab-jira.atlassian.net/browse/DEMO-1][1]
Some prelude text `adf-inlineCard:
{"@context"=>"https://json-ld.org/contexts/person.jsonld",
"@id"=>"http://dbpedia.org/resource/John_Lennon", "name"=>"John Lennon",
"born"=>"1940-10-09",
"spouse"=>"http://dbpedia.org/resource/Cynthia_Lennon"}` some following
text
[1]: https://gitlab-jira.atlassian.net/browse/DEMO-1
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a second paragraph"
}
]
}
]
}
}
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a sample paragraph"
},
{
"type": "text",
"text": " with lorem ipsum dolor sit amet..."
}
]
}
{
"version": 1,
"type": "doc",
"content": [
{
"type": "invalid",
"content": [
{
"type": "text",
"text": "This is a sample paragraph"
},
{
"type": "text",
"text": " with lorem ipsum dolor sit amet..."
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a second paragraph"
}
]
}
]
}
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a "
},
{
"type": "text",
"text": "link without title",
"marks": [
{
"type": "link",
"attrs": {
"href": "http://example.com"
}
}
]
},
{
"type": "text",
"text": " and a "
},
{
"type": "text",
"text": "link with title",
"marks": [
{
"type": "link",
"attrs": {
"href": "http://example.net",
"title": "Link Title"
}
}
]
}
]
}
]
}
This is a [link without title][1] and a [link with title][2]
[1]: http://example.com
[2]: http://example.net "Link Title"
{
"version": 1,
"type": "doc",
"content": [
{
"type": "mediaGroup",
"content": [
{
"type": "media",
"attrs": {
"id": "79411c6b-50e0-477f-b4ed-ac3a5887750c",
"type": "file",
"collection": "jira-10050-field-description",
"width": 400,
"height": 400
}
},
{
"type": "media",
"attrs": {
"id": "79411c6b-50e0-477f-b4ed-abcde",
"type": "file",
"collection": "jira-10050-field-description",
"width": 400,
"height": 400
}
}
]
},
{
"type": "rule"
},
{
"type": "mediaGroup",
"content": [
{
"type": "media",
"attrs": {
"id": "79411c6b-50e0-477f-b4ed-ac3a5887750c-link1",
"type": "link",
"collection": "jira-10050-field-description-links",
"width": 400,
"height": 400
}
},
{
"type": "media",
"attrs": {
"id": "79411c6b-50e0-477f-b4ed-ac3a5887750c-link2",
"type": "link",
"collection": "jira-10050-field-description-links",
"width": 400,
"height": 400
}
}
]
}
]
}
* ![jira-10050-field-description](adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c)
* ![jira-10050-field-description](adf-media://79411c6b-50e0-477f-b4ed-abcde)
* * *
* [adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c-link1](adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c-link1)
* [adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c-link2](adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c-link2)
{
"version": 1,
"type": "doc",
"content": [
{
"type": "mediaSingle",
"attrs": {
"layout": "center"
},
"content": [
{
"type": "media",
"attrs": {
"id": "79411c6b-50e0-477f-b4ed-ac3a5887750c",
"type": "file",
"collection": "jira-10050-field-description",
"width": 400,
"height": 400
}
}
]
},
{
"type": "mediaSingle",
"attrs": {
"layout": "center"
},
"content": [
{
"type": "media",
"attrs": {
"id": "79411c6b-50e0-477f-b4ed-abcd",
"type": "file",
"collection": "another-jira-10050-field-description",
"width": 400,
"height": 400
}
}
]
}
]
}
![jira-10050-field-description](adf-media://79411c6b-50e0-477f-b4ed-ac3a5887750c)
![another-jira-10050-field-description](adf-media://79411c6b-50e0-477f-b4ed-abcd)
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Mentioning "
},
{
"type": "mention",
"attrs": {
"id": "ABCDE-ABCDE-ABCDE-ABCDE",
"text": "@testuser",
"userType": "APP"
}
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Mentioning "
},
{
"type": "mention",
"attrs": {
"id": "ABCDE-ABCDE-ABCDE-ABCDE",
"text": "@test user",
"userType": "APP"
}
},
{
"type": "text",
"text": " with space in user name"
}
]
}
]
}
Mentioning @adf-mention:testuser
Mentioning @adf-mention:\"test user\" with space in user name
{
"version": 1,
"type": "doc",
"content": [
{
"type": "orderedList",
"content": [
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list Item 1"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 2"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 3"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 4"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 5"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 6"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 7"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 8"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 9"
}
]
}
]
},
{
"type": "listItem",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Number list item 10"
}
]
}
]
}
]
}
]
}
1. Number list Item 1
2. Number list item 2
3. Number list item 3
4. Number list item 4
5. Number list item 5
6. Number list item 6
7. Number list item 7
8. Number list item 8
9. Number list item 9
10. Number list item 10
{
"version": 1,
"type": "doc",
"content": [
{
"type": "panel",
"attrs": {
"panelType": "success"
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Success info panel"
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Second paragraph"
}
]
}
]
},
{
"type": "panel",
"attrs": {
"panelType": "info"
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Info info panel"
}
]
}
]
},
{
"type": "panel",
"attrs": {
"panelType": "note"
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Note info panel"
}
]
}
]
},
{
"type": "panel",
"attrs": {
"panelType": "warning"
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Warning info panel"
}
]
}
]
},
{
"type": "panel",
"attrs": {
"panelType": "error"
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Error info panel"
}
]
}
]
},
{
"type": "panel",
"attrs": {
"panelType": "unknown"
},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Unknown panel"
}
]
}
]
}
]
}
> \:white\_check\_mark: Success info panel
>
> Second paragraph
> \:information\_source: Info info panel
> \:notepad\_spiral: Note info panel
> \:warning: Warning info panel
> \:octagonal\_sign: Error info panel
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a sample paragraph"
},
{
"type": "text",
"text": " with lorem ipsum dolor sit amet..."
}
]
},
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is a second paragraph"
}
]
}
]
}
This is a sample paragraph with lorem ipsum dolor sit amet...
This is a second paragraph
{
"version": 1,
"type": "doc",
"content": [
{
"type": "rule"
}
]
}
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is "
},
{
"type": "text",
"text": "stricken",
"marks": [
{
"type": "strike"
}
]
},
{
"type": "text",
"text": " and "
},
{
"type": "text",
"text": "superscripted",
"marks": [
{
"type": "subsup",
"attrs": {
"type": "sup"
}
}
]
},
{
"type": "text",
"text": " and "
},
{
"type": "text",
"text": "subscripted",
"marks": [
{
"type": "subsup",
"attrs": {
"type": "sub"
}
}
]
}
]
}
]
}
This is <del>stricken</del> and <sup>superscripted</sup> and
<sub>subscripted</sub>
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Hello "
},
{
"type": "text",
"text": "strong",
"marks": [
{
"type": "strong"
}
]
},
{
"type": "text",
"text": " and "
},
{
"type": "text",
"text": "emphasis",
"marks": [
{
"type": "em"
}
]
},
{
"type": "text",
"text": " and "
},
{
"type": "text",
"text": "strongly emphasised",
"marks": [
{
"type": "em"
},
{
"type": "strong"
}
]
}
]
}
]
}
Hello **strong** and *emphasis* and ***strongly emphasised***
{
"version": 1,
"type": "doc",
"content": [
{
"type": "table",
"attrs": {
"isNumberColumnEnabled": false,
"layout": "default"
},
"content": [
{
"type": "tableRow",
"content": [
{
"type": "tableCell",
"attrs": {},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Row one, cell one",
"marks": [
{
"type": "strong"
}
]
}
]
}
]
},
{
"type": "tableCell",
"attrs": {},
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "Row one, cell two"
}
]
}
]
}
]
}
]
}
]
}
<table>
<tbody>
<tr>
<td>
**Row one, cell one**
</td>
<td>
Row one, cell two
</td>
</tr>
</tbody>
</table>
{
"version": 1,
"type": "doc",
"content": [
{
"type": "paragraph",
"content": [
{
"type": "text",
"text": "This is "
},
{
"type": "text",
"text": "underlined",
"marks": [
{
"type": "underline"
}
]
},
{
"type": "text",
"text": " and "
},
{
"type": "text",
"text": "red",
"marks": [
{
"type": "textColor",
"attrs": {
"color": "#ff6347"
}
}
]
}
]
}
]
}
This is <u>underlined</u> and <span color="#ff6347">red</span>
# frozen_string_literal: true
require 'spec_helper'
describe Banzai::Filter::JiraImport::AdfToCommonmarkFilter do
include FilterSpecHelper
let_it_be(:fixtures_path) { 'lib/kramdown/atlassian_document_format' }
it 'renders a complex document' do
source = fixture_file(File.join(fixtures_path, 'complex_document.json'))
target = fixture_file(File.join(fixtures_path, 'complex_document.md'))
expect(filter(source)).to eq target
end
it 'renders original source when it is invalid JSON' do
source = fixture_file(File.join(fixtures_path, 'invalid_json.json'))
expect(filter(source)).to eq "Invalid Atlassian Document Format JSON\n\n#{source}"
end
it 'renders original source when missing document node' do
source = fixture_file(File.join(fixtures_path, 'invalid_no_doc.json'))
expect(filter(source)).to eq "Invalid Atlassian Document Format JSON\n\n#{source}"
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Banzai::Pipeline::JiraImport::AdfCommonmarkPipeline do
let_it_be(:fixtures_path) { 'lib/kramdown/atlassian_document_format' }
it 'converts text in Atlassian Document Format ' do
source = fixture_file(File.join(fixtures_path, 'paragraph.json'))
target = fixture_file(File.join(fixtures_path, 'paragraph.md'))
output = described_class.call(source, {})[:output]
expect(output).to eq target
end
end
# frozen_string_literal: true
require 'spec_helper'
context Kramdown::Parser::AtlassianDocumentFormat do
let_it_be(:options) { { input: 'AtlassianDocumentFormat', html_tables: true } }
let_it_be(:fixtures_path) { 'lib/kramdown/atlassian_document_format' }
context 'markdown render' do
shared_examples 'render elements to markdown' do |base_name|
let(:json_file) { "#{base_name}.json" }
let(:markdown_file) { "#{base_name}.md" }
it "renders #{base_name}" do
source = fixture_file(File.join(fixtures_path, json_file))
target = fixture_file(File.join(fixtures_path, markdown_file))
parser = Kramdown::Document.new(source, options)
expect(parser.to_commonmark).to eq target
end
end
it_behaves_like 'render elements to markdown', 'blockquote'
it_behaves_like 'render elements to markdown', 'bullet_list'
it_behaves_like 'render elements to markdown', 'code_block'
it_behaves_like 'render elements to markdown', 'emoji'
it_behaves_like 'render elements to markdown', 'hard_break'
it_behaves_like 'render elements to markdown', 'heading'
it_behaves_like 'render elements to markdown', 'inline_card'
it_behaves_like 'render elements to markdown', 'media_group'
it_behaves_like 'render elements to markdown', 'media_single'
it_behaves_like 'render elements to markdown', 'mention'
it_behaves_like 'render elements to markdown', 'ordered_list'
it_behaves_like 'render elements to markdown', 'panel'
it_behaves_like 'render elements to markdown', 'paragraph'
it_behaves_like 'render elements to markdown', 'rule'
it_behaves_like 'render elements to markdown', 'table'
it_behaves_like 'render elements to markdown', 'strong_em_mark'
it_behaves_like 'render elements to markdown', 'code_mark'
it_behaves_like 'render elements to markdown', 'link_mark'
it_behaves_like 'render elements to markdown', 'strike_sup_sub_mark'
it_behaves_like 'render elements to markdown', 'underline_text_color_mark'
it_behaves_like 'render elements to markdown', 'complex_document'
it 'renders header id to html' do
source = fixture_file(File.join(fixtures_path, 'heading.json'))
parser = Kramdown::Document.new(source, options)
expect(parser.to_html).to include('id="header-2"')
end
it 'logs an error with invalid json' do
source = fixture_file(File.join(fixtures_path, 'invalid_json.json'))
expect(Gitlab::AppLogger).to receive(:error).with(/Invalid Atlassian Document Format JSON/)
expect(Gitlab::AppLogger).to receive(:error).with(any_args)
expect { Kramdown::Document.new(source, options) }.to raise_error(::Kramdown::Error, /Invalid Atlassian Document Format JSON/)
end
it 'logs an error if no valid document node' do
source = fixture_file(File.join(fixtures_path, 'invalid_no_doc.json'))
expect(Gitlab::AppLogger).to receive(:error).with(/Invalid Atlassian Document Format JSON/)
expect(Gitlab::AppLogger).to receive(:error).with(any_args)
expect { Kramdown::Document.new(source, options) }.to raise_error(::Kramdown::Error, /Invalid Atlassian Document Format JSON/)
end
it 'invalid node gets ignored' do
source = fixture_file(File.join(fixtures_path, 'invalid_node_type.json'))
parser = Kramdown::Document.new(source, options)
expect(parser.to_commonmark).to eq "This is a second paragraph\n\n"
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment