kramdown-prismic 0.3.0 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|