kramdown-prismic 0.3.0 → 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{Changelog.md → CHANGELOG.md} +18 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +20 -3
- data/Rakefile +3 -2
- data/bin/html2prismic +6 -0
- data/bin/markdown2prismic +6 -0
- data/bin/prismic2markdown +8 -0
- data/kramdown-prismic.gemspec +12 -8
- data/kramdown1.gemfile +2 -0
- data/kramdown2.gemfile +2 -0
- data/lib/kramdown/converter/prismic.rb +89 -38
- data/lib/kramdown/parser/prismic.rb +60 -29
- data/lib/kramdown-prismic/version.rb +3 -1
- data/lib/kramdown-prismic.rb +2 -0
- data/test/converter_test.rb +208 -105
- data/test/parser_test.rb +173 -52
- metadata +10 -5
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73ce49b872adc3dd34de55efc6c45bdde6ab2ec5cfd04fc4192555639ed63fb3
|
4
|
+
data.tar.gz: f95a92886b915b6bf5c3b283368e84fcb4591b5b3f45e998a7ed13beb31e788f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cd76efd9fb572c3f921c44b0d2ee6f6748c9132ac5827d373e581ec19361609f73acb1bac3fb8f27bc6e5c53219353e363e5a05f71dacbfbef5eb7f1d88ca16
|
7
|
+
data.tar.gz: 03b6033f3576720dfaa823c808c9d29f1264813d8ec82b807f3bc72217263179f110f380b87fac3ea41157cbd4da189254a08edeb4089cb139221b6083bef86a
|
@@ -1,5 +1,23 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## Version 0.3.4
|
4
|
+
|
5
|
+
- Convert `strong` and `em` elements when converting HTML documents.
|
6
|
+
|
7
|
+
## Version 0.3.3
|
8
|
+
|
9
|
+
- Renable converting xml comments
|
10
|
+
|
11
|
+
## Version 0.3.2
|
12
|
+
|
13
|
+
- Parse ordered and unordered lists
|
14
|
+
- Parse image with link
|
15
|
+
|
16
|
+
## Version 0.3.1
|
17
|
+
|
18
|
+
- Add binaries `html2primisc`, `markdown2prismic` and `primisc2markdown`.
|
19
|
+
- Add parsed embed support
|
20
|
+
|
3
21
|
## Version 0.3.0
|
4
22
|
|
5
23
|
- Relax the kramdown dependency to allows the version 2.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
# Kramdown Prismic
|
2
2
|
|
3
|
-
A [Kramdown][] parser and converter to convert documents into [prismic][] rich text format and
|
3
|
+
A [Kramdown][] parser and converter to convert documents into [prismic][] rich text format and the other way around.
|
4
4
|
|
5
|
-
A useful usage is to convert markdown documents to prismic for import purpose. Then you can even convert prismic format back to markdown.
|
5
|
+
A useful usage is to convert markdown documents to prismic for [import purpose][prismic-import]. Then you can even convert prismic format back to markdown.
|
6
6
|
|
7
7
|
## Status
|
8
8
|
|
9
9
|
The converter part (kramdown to prismic) is working and fairly complete. See *Difference between markdown and rich text* below to know more about limitations.
|
10
10
|
|
11
|
-
The parser part is quite new and not feature complete
|
11
|
+
The parser part is quite new and not feature complete.
|
12
12
|
|
13
13
|
## Install
|
14
14
|
|
@@ -18,6 +18,22 @@ gem 'kramdown-prismic', '~> 0.1'
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
+
### With executables
|
22
|
+
|
23
|
+
*markdown2prismic*:
|
24
|
+
|
25
|
+
markdown2prismic $'# My Title\n\nHello world'
|
26
|
+
|
27
|
+
*html2prismic*:
|
28
|
+
|
29
|
+
html2prismic '<h1>My Title</h1><p>Hello world</p>'
|
30
|
+
|
31
|
+
*prismic2markdown*:
|
32
|
+
|
33
|
+
prismic2markdown '[{"type":"heading1","content":{"text":"My Title","spans":[]}},{"type":"paragraph","content":{"text":"Test","spans":[]}}]'
|
34
|
+
|
35
|
+
### As a library
|
36
|
+
|
21
37
|
**Convert kramdown documents to Prismic**
|
22
38
|
|
23
39
|
```ruby
|
@@ -123,3 +139,4 @@ MIT
|
|
123
139
|
|
124
140
|
[Kramdown]: https://kramdown.gettalong.org/
|
125
141
|
[prismic]: https://prismic.io/
|
142
|
+
[prismic-import]: https://prismic.io/docs/core-concepts/how-to-import-content
|
data/Rakefile
CHANGED
data/bin/html2prismic
ADDED
data/kramdown-prismic.gemspec
CHANGED
@@ -1,21 +1,25 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require File.expand_path('lib/kramdown-prismic/version', __dir__)
|
3
4
|
|
4
5
|
Gem::Specification.new do |s|
|
5
6
|
s.name = 'kramdown-prismic'
|
6
7
|
s.version = KramdownPrismic::VERSION
|
7
|
-
s.summary =
|
8
|
-
s.description =
|
9
|
-
s.authors = [
|
8
|
+
s.summary = 'A Kramdown converter to convert documents into prismic rich text format and the other way around.'
|
9
|
+
s.description = 'A Kramdown converter to convert documents into prismic rich text format and the other way around.'
|
10
|
+
s.authors = ['François de Metz']
|
10
11
|
s.email = 'francois@2metz.fr'
|
11
12
|
|
13
|
+
s.executables << 'markdown2prismic'
|
14
|
+
s.executables << 'html2prismic'
|
15
|
+
s.executables << 'prismic2markdown'
|
12
16
|
s.files = `git ls-files`.split("\n")
|
13
17
|
s.test_files = `git ls-files -- test/*`.split("\n")
|
14
18
|
|
15
19
|
s.homepage = 'https://github.com/stormz/kramdown-prismic'
|
16
20
|
s.license = 'MIT'
|
17
21
|
|
18
|
-
s.add_dependency
|
19
|
-
s.add_development_dependency
|
20
|
-
s.add_development_dependency
|
22
|
+
s.add_dependency 'kramdown', '>= 1', '< 3'
|
23
|
+
s.add_development_dependency 'minitest', '~> 5.0'
|
24
|
+
s.add_development_dependency 'rake', '~> 13.0'
|
21
25
|
end
|
data/kramdown1.gemfile
CHANGED
data/kramdown2.gemfile
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'kramdown/converter/base'
|
2
4
|
|
3
5
|
module Kramdown
|
4
6
|
module Converter
|
5
7
|
class Prismic < Base
|
6
8
|
def convert(root)
|
7
|
-
cleanup_ast(root).map
|
9
|
+
cleanup_ast(root).map do |child|
|
8
10
|
convert_element(child)
|
9
|
-
|
11
|
+
end.compact.flatten
|
10
12
|
end
|
11
13
|
|
12
14
|
private
|
@@ -21,22 +23,23 @@ module Kramdown
|
|
21
23
|
end
|
22
24
|
|
23
25
|
def remove_blanks(root)
|
24
|
-
root.children = root.children.
|
26
|
+
root.children = root.children.each_with_object([]) do |child, memo|
|
25
27
|
unless child.type == :blank
|
26
28
|
remove_blanks(child)
|
27
29
|
memo << child
|
28
30
|
end
|
29
|
-
memo
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
34
|
def extract_non_nestable_elements(child, elements)
|
34
|
-
child.children = child.children.
|
35
|
-
if element.type == :a && element.children.size
|
35
|
+
child.children = child.children.each_with_object([]) do |element, memo|
|
36
|
+
if element.type == :a && element.children.size == 1 && element.children.first.type == :img
|
36
37
|
elements << element
|
37
38
|
elsif element.type == :img
|
38
39
|
elements << element
|
39
|
-
|
40
|
+
if child.children.size > 1
|
41
|
+
warning('images inside content will be moved to the top level and may be rendered differently')
|
42
|
+
end
|
40
43
|
elsif element.type == :ul
|
41
44
|
warning('nested list moved to the top level')
|
42
45
|
elements << element
|
@@ -45,7 +48,6 @@ module Kramdown
|
|
45
48
|
memo << element
|
46
49
|
extract_non_nestable_elements(element, elements)
|
47
50
|
end
|
48
|
-
memo
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -61,9 +63,10 @@ module Kramdown
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def convert_p(element)
|
64
|
-
return nil if element.children.size
|
66
|
+
return nil if element.children.size.zero?
|
67
|
+
|
65
68
|
{
|
66
|
-
type:
|
69
|
+
type: 'paragraph',
|
67
70
|
content: extract_content(element)
|
68
71
|
}
|
69
72
|
end
|
@@ -106,8 +109,7 @@ module Kramdown
|
|
106
109
|
}
|
107
110
|
end
|
108
111
|
|
109
|
-
def convert_hr(element)
|
110
|
-
end
|
112
|
+
def convert_hr(element); end
|
111
113
|
|
112
114
|
def convert_img(element)
|
113
115
|
{
|
@@ -118,9 +120,9 @@ module Kramdown
|
|
118
120
|
},
|
119
121
|
data: {
|
120
122
|
origin: {
|
121
|
-
url: element.attr[
|
123
|
+
url: element.attr['src']
|
122
124
|
},
|
123
|
-
alt: element.attr[
|
125
|
+
alt: element.attr['alt']
|
124
126
|
}
|
125
127
|
}
|
126
128
|
end
|
@@ -146,40 +148,85 @@ module Kramdown
|
|
146
148
|
}
|
147
149
|
end
|
148
150
|
|
151
|
+
def convert_strong(element)
|
152
|
+
convert_sub_html_element(element, 'strong')
|
153
|
+
end
|
154
|
+
|
155
|
+
def convert_em(element)
|
156
|
+
convert_sub_html_element(element, 'em')
|
157
|
+
end
|
158
|
+
|
159
|
+
def convert_sub_html_element(element, type)
|
160
|
+
content = extract_content(element)
|
161
|
+
content[:spans].push({ type: type, start: 0, end: content[:text].size })
|
162
|
+
{
|
163
|
+
type: 'paragraph',
|
164
|
+
content: content
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
149
168
|
def convert_html_element(element)
|
150
|
-
|
151
|
-
|
169
|
+
if element.value == 'iframe'
|
170
|
+
{
|
171
|
+
content: {
|
172
|
+
spans: [],
|
173
|
+
text: ''
|
174
|
+
},
|
175
|
+
type: 'embed',
|
176
|
+
data: {
|
177
|
+
embed_url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
|
178
|
+
type: 'link'
|
179
|
+
}
|
180
|
+
}
|
181
|
+
else
|
182
|
+
warning('translating html elements is not supported')
|
183
|
+
nil
|
184
|
+
end
|
152
185
|
end
|
153
186
|
|
154
|
-
def convert_table(
|
187
|
+
def convert_table(_element)
|
155
188
|
warning('translating table is not supported')
|
156
189
|
nil
|
157
190
|
end
|
158
191
|
|
159
|
-
def convert_dl(
|
192
|
+
def convert_dl(_element)
|
160
193
|
warning('translating dl is not supported')
|
161
194
|
nil
|
162
195
|
end
|
163
196
|
|
164
|
-
def convert_math(
|
197
|
+
def convert_math(_element)
|
165
198
|
warning('translating math is not supported')
|
166
199
|
nil
|
167
200
|
end
|
168
201
|
|
169
|
-
def convert_comment(
|
202
|
+
def convert_comment(_element)
|
170
203
|
warning('translating comment is not supported')
|
171
204
|
nil
|
172
205
|
end
|
173
206
|
|
174
|
-
def
|
207
|
+
def convert_xml_comment(_element)
|
208
|
+
warning('translating xml comment is not supported')
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
|
212
|
+
def convert_raw(_element)
|
175
213
|
warning('translating raw is not supported')
|
176
214
|
nil
|
177
215
|
end
|
178
216
|
|
179
|
-
def
|
180
|
-
|
217
|
+
def convert_text(element)
|
218
|
+
{
|
219
|
+
type: 'paragraph',
|
220
|
+
content: {
|
221
|
+
text: element.value,
|
222
|
+
spans: []
|
223
|
+
}
|
224
|
+
}
|
225
|
+
end
|
226
|
+
|
227
|
+
def extract_content(element, memo = { text: '', spans: [] })
|
228
|
+
element.children.each_with_object(memo) do |child, memo2|
|
181
229
|
send("extract_span_#{child.type}", child, memo2)
|
182
|
-
memo2
|
183
230
|
end
|
184
231
|
end
|
185
232
|
|
@@ -200,7 +247,7 @@ module Kramdown
|
|
200
247
|
insert_span(element, memo, {
|
201
248
|
type: 'hyperlink',
|
202
249
|
data: {
|
203
|
-
url: element.attr[
|
250
|
+
url: element.attr['href']
|
204
251
|
}
|
205
252
|
})
|
206
253
|
end
|
@@ -221,7 +268,7 @@ module Kramdown
|
|
221
268
|
extract_content(element, memo)
|
222
269
|
end
|
223
270
|
|
224
|
-
def extract_span_br(
|
271
|
+
def extract_span_br(_element, memo)
|
225
272
|
memo[:text] += "\n"
|
226
273
|
end
|
227
274
|
|
@@ -230,11 +277,11 @@ module Kramdown
|
|
230
277
|
memo[:text] += element.value
|
231
278
|
end
|
232
279
|
|
233
|
-
def extract_span_html_element(
|
280
|
+
def extract_span_html_element(_element, _memo)
|
234
281
|
warning('translating html elements is not supported')
|
235
282
|
end
|
236
283
|
|
237
|
-
def extract_span_footnote(
|
284
|
+
def extract_span_footnote(_element, _memo)
|
238
285
|
warning('translating footnote is not supported')
|
239
286
|
end
|
240
287
|
|
@@ -243,17 +290,21 @@ module Kramdown
|
|
243
290
|
memo[:text] += element.value
|
244
291
|
end
|
245
292
|
|
293
|
+
def extract_span_xml_comment(element, memo)
|
294
|
+
warning('translating xml comment is not supported')
|
295
|
+
end
|
296
|
+
|
246
297
|
TYPOGRAPHIC_SYMS = {
|
247
|
-
mdash: [
|
248
|
-
ndash: [
|
249
|
-
hellip: [
|
250
|
-
laquo_space: [
|
251
|
-
raquo_space: [
|
252
|
-
laquo: [
|
253
|
-
raquo: [
|
254
|
-
}
|
298
|
+
mdash: [Utils::Entities.entity('mdash')],
|
299
|
+
ndash: [Utils::Entities.entity('ndash')],
|
300
|
+
hellip: [Utils::Entities.entity('hellip')],
|
301
|
+
laquo_space: [Utils::Entities.entity('laquo'), Utils::Entities.entity('nbsp')],
|
302
|
+
raquo_space: [Utils::Entities.entity('nbsp'), Utils::Entities.entity('raquo')],
|
303
|
+
laquo: [Utils::Entities.entity('laquo')],
|
304
|
+
raquo: [Utils::Entities.entity('raquo')]
|
305
|
+
}.freeze
|
255
306
|
def extract_span_typographic_sym(element, memo)
|
256
|
-
value = TYPOGRAPHIC_SYMS[element.value].map
|
307
|
+
value = TYPOGRAPHIC_SYMS[element.value].map(&:char).join('')
|
257
308
|
memo[:text] += value
|
258
309
|
end
|
259
310
|
|
@@ -262,7 +313,7 @@ module Kramdown
|
|
262
313
|
end
|
263
314
|
|
264
315
|
def extract_span_smart_quote(element, memo)
|
265
|
-
memo[:text] +=
|
316
|
+
memo[:text] += Utils::Entities.entity(element.value.to_s).char
|
266
317
|
end
|
267
318
|
end
|
268
319
|
end
|
@@ -1,54 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Kramdown
|
2
4
|
module Parser
|
3
5
|
class Prismic < Base
|
4
6
|
def parse
|
5
7
|
@root.options[:encoding] = 'UTF-8'
|
6
|
-
@root.children = @source.
|
7
|
-
|
8
|
-
if type.match(/heading/)
|
9
|
-
type = 'heading'
|
10
|
-
end
|
11
|
-
element = send("parse_#{type}", block)
|
12
|
-
parse_spans(element, block)
|
13
|
-
element
|
8
|
+
@root.children = @source.reduce([]) do |memo, block|
|
9
|
+
parse_element(block, memo)
|
14
10
|
end
|
15
11
|
end
|
16
12
|
|
17
13
|
private
|
18
14
|
|
15
|
+
def parse_element(block, memo)
|
16
|
+
type = block[:type].gsub('-', '_')
|
17
|
+
type = 'heading' if type.match(/heading/)
|
18
|
+
if type == 'list_item'
|
19
|
+
parse_list(:ul, block, memo)
|
20
|
+
memo
|
21
|
+
elsif type == 'o_list_item'
|
22
|
+
parse_list(:ol, block, memo)
|
23
|
+
memo
|
24
|
+
else
|
25
|
+
element = send("parse_#{type}", block)
|
26
|
+
parse_spans(element, block)
|
27
|
+
memo << element
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
19
31
|
def parse_heading(block)
|
20
32
|
level = block[:type].match(/heading([1-6])/)[1].to_i
|
21
|
-
|
33
|
+
Element.new(:header, nil, nil, { level: level, raw_text: '' })
|
22
34
|
end
|
23
35
|
|
24
|
-
def parse_paragraph(
|
25
|
-
|
36
|
+
def parse_paragraph(_block)
|
37
|
+
Element.new(:p)
|
26
38
|
end
|
27
39
|
|
28
40
|
def parse_image(block)
|
29
|
-
p =
|
30
|
-
img =
|
31
|
-
|
41
|
+
p = Element.new(:p)
|
42
|
+
img = Element.new(:img, nil, { 'src' => block[:data][:origin][:url], 'alt' => block[:data][:alt] })
|
43
|
+
if block[:data][:linkTo]
|
44
|
+
a = Element.new(:a, nil, { 'href' => block[:data][:linkTo][:url] })
|
45
|
+
a.children << img
|
46
|
+
p.children << a
|
47
|
+
else
|
48
|
+
p.children << img
|
49
|
+
end
|
32
50
|
p
|
33
51
|
end
|
34
52
|
|
35
|
-
def parse_preformatted(
|
36
|
-
|
53
|
+
def parse_preformatted(_block)
|
54
|
+
Element.new(:blockquote)
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_list(type, block, memo)
|
58
|
+
list = memo.last
|
59
|
+
unless list && list.type == type
|
60
|
+
list = Element.new(type)
|
61
|
+
memo << list
|
62
|
+
end
|
63
|
+
li = Element.new(:li, nil, nil)
|
64
|
+
list.children << li
|
65
|
+
p = Element.new(:p, nil, nil, transparent: true)
|
66
|
+
li.children << p
|
67
|
+
parse_spans(p, block)
|
37
68
|
end
|
38
69
|
|
39
70
|
def parse_embed(block)
|
40
|
-
|
71
|
+
Element.new(:html_element, 'iframe', { src: block[:data][:embed_url] })
|
41
72
|
end
|
42
73
|
|
43
74
|
def parse_spans(element, block)
|
44
75
|
stack = []
|
45
76
|
|
46
77
|
(block[:content][:text].size + 1).times do |index|
|
47
|
-
|
48
78
|
starting_spans = find_starting_spans_for(block, index)
|
49
79
|
ending_spans = find_ending_spans_for(block, index)
|
50
80
|
|
51
|
-
ending_spans.each do |
|
81
|
+
ending_spans.each do |_ending_span|
|
52
82
|
el = stack.pop
|
53
83
|
if stack.empty?
|
54
84
|
element.children << el
|
@@ -57,22 +87,23 @@ module Kramdown
|
|
57
87
|
end
|
58
88
|
end
|
59
89
|
starting_spans.each do |starting_span|
|
60
|
-
stack << if starting_span[:type] ==
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
90
|
+
stack << if starting_span[:type] == 'hyperlink'
|
91
|
+
Element.new(:a, nil, { 'href' => starting_span[:data][:url] })
|
92
|
+
else
|
93
|
+
Element.new(starting_span[:type].to_sym)
|
94
|
+
end
|
65
95
|
end
|
66
96
|
|
67
97
|
char = block[:content][:text][index]
|
68
98
|
next if char.nil?
|
99
|
+
|
69
100
|
current_text = if stack.empty?
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
101
|
+
element.children.last
|
102
|
+
else
|
103
|
+
stack[-1].children.last
|
104
|
+
end
|
74
105
|
if current_text.nil? || current_text.type != :text
|
75
|
-
current_text = Element.new(:text,
|
106
|
+
current_text = Element.new(:text, '')
|
76
107
|
if stack.empty?
|
77
108
|
element.children << current_text
|
78
109
|
else
|