synotion 0.1.0 → 0.2.0
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 +6 -0
- data/README.md +3 -1
- data/lib/synotion/client.rb +4 -4
- data/lib/synotion/markdown_converter.rb +120 -9
- data/lib/synotion/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6072eda9ba4254047b5c306cc68ee3bc5ca3c8612fd1f12217490d421845f385
|
|
4
|
+
data.tar.gz: 1e13fbcdcd01cb50c8e3495eb83353eac569b792d40b839f8054865a685c967c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1781fb13cd1323a299806b8fbf9098f695e5850cca0c5689c26f3d0d148be0f1d01a4fa9be58c5be5abd583a093d9ca52a909783f03cc44df32f5d572cfc8025
|
|
7
|
+
data.tar.gz: 0007ce05df18d685e5fea89cedc55a94b639f585153647569020f0cb4e0c33fc5113679b65ff5cc5595bc082f2cd78f5763a4143cf7164b8d4127f508dfe726c
|
data/CHANGELOG.md
CHANGED
|
@@ -7,5 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## Unreleased
|
|
9
9
|
|
|
10
|
+
## [0.2.0] - 2025-12-16
|
|
11
|
+
|
|
12
|
+
- Add support for tables and inline links in Markdown to Notion conversion.
|
|
13
|
+
|
|
14
|
+
## [0.1.0] - 2025-12-15
|
|
15
|
+
|
|
10
16
|
- Initial release
|
|
11
17
|
|
data/README.md
CHANGED
|
@@ -111,7 +111,7 @@ unique_property: source_file
|
|
|
111
111
|
|
|
112
112
|
### Supported Markdown Elements
|
|
113
113
|
|
|
114
|
-
- Headings (H1, H2, H3)
|
|
114
|
+
- Headings (H1, H2, H3+)
|
|
115
115
|
- Paragraphs
|
|
116
116
|
- Code blocks with syntax highlighting
|
|
117
117
|
- Bulleted lists
|
|
@@ -119,6 +119,8 @@ unique_property: source_file
|
|
|
119
119
|
- Quotes
|
|
120
120
|
- Dividers
|
|
121
121
|
- Todo items / Checkboxes
|
|
122
|
+
- Tables (converted to Notion table blocks)
|
|
123
|
+
- Links (external URLs converted to clickable links)
|
|
122
124
|
- YAML front matter
|
|
123
125
|
|
|
124
126
|
## Notion Setup
|
data/lib/synotion/client.rb
CHANGED
|
@@ -78,10 +78,10 @@ module Synotion
|
|
|
78
78
|
cursor = nil
|
|
79
79
|
|
|
80
80
|
loop do
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
81
|
+
params = { block_id: page_id }
|
|
82
|
+
params[:start_cursor] = cursor if cursor
|
|
83
|
+
|
|
84
|
+
response = api_client.block_children(**params)
|
|
85
85
|
|
|
86
86
|
blocks.concat(response.results)
|
|
87
87
|
|
|
@@ -30,6 +30,10 @@ module Synotion
|
|
|
30
30
|
code_block, lines_consumed = parse_code_block(lines[i..-1])
|
|
31
31
|
blocks << code_block if code_block
|
|
32
32
|
i += lines_consumed
|
|
33
|
+
elsif line.start_with?('|') && is_table?(lines[i..-1])
|
|
34
|
+
table_block, lines_consumed = parse_table(lines[i..-1])
|
|
35
|
+
blocks << table_block if table_block
|
|
36
|
+
i += lines_consumed
|
|
33
37
|
elsif line.match?(/^\s*[-*]\s+\[[ x]\]/)
|
|
34
38
|
blocks << parse_todo(line)
|
|
35
39
|
i += 1
|
|
@@ -96,7 +100,7 @@ module Synotion
|
|
|
96
100
|
{
|
|
97
101
|
type: heading_type,
|
|
98
102
|
heading_type => {
|
|
99
|
-
rich_text:
|
|
103
|
+
rich_text: parse_inline_formatting(text.strip)
|
|
100
104
|
}
|
|
101
105
|
}
|
|
102
106
|
end
|
|
@@ -150,7 +154,7 @@ module Synotion
|
|
|
150
154
|
items << {
|
|
151
155
|
type: type.to_s,
|
|
152
156
|
type => {
|
|
153
|
-
rich_text:
|
|
157
|
+
rich_text: parse_inline_formatting(text)
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
i += 1
|
|
@@ -165,7 +169,7 @@ module Synotion
|
|
|
165
169
|
{
|
|
166
170
|
type: 'quote',
|
|
167
171
|
quote: {
|
|
168
|
-
rich_text:
|
|
172
|
+
rich_text: parse_inline_formatting(text.strip)
|
|
169
173
|
}
|
|
170
174
|
}
|
|
171
175
|
end
|
|
@@ -178,7 +182,7 @@ module Synotion
|
|
|
178
182
|
{
|
|
179
183
|
type: 'to_do',
|
|
180
184
|
to_do: {
|
|
181
|
-
rich_text:
|
|
185
|
+
rich_text: parse_inline_formatting(text),
|
|
182
186
|
checked: checked
|
|
183
187
|
}
|
|
184
188
|
}
|
|
@@ -197,7 +201,7 @@ module Synotion
|
|
|
197
201
|
i += 1
|
|
198
202
|
end
|
|
199
203
|
|
|
200
|
-
return [nil, i] if paragraph_lines.empty?
|
|
204
|
+
return [nil, [i, 1].max] if paragraph_lines.empty?
|
|
201
205
|
|
|
202
206
|
text = paragraph_lines.join(' ').strip
|
|
203
207
|
rich_text = parse_inline_formatting(text)
|
|
@@ -216,10 +220,117 @@ module Synotion
|
|
|
216
220
|
segments = []
|
|
217
221
|
current_pos = 0
|
|
218
222
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
while current_pos < text.length
|
|
224
|
+
link_match = text[current_pos..-1].match(/\[([^\]]+)\]\(([^\)]+)\)/)
|
|
225
|
+
|
|
226
|
+
if link_match
|
|
227
|
+
pre_text = text[current_pos...(current_pos + link_match.begin(0))]
|
|
228
|
+
if pre_text.length > 0
|
|
229
|
+
segments << {
|
|
230
|
+
type: 'text',
|
|
231
|
+
text: { content: pre_text }
|
|
232
|
+
}
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
link_text = link_match[1]
|
|
236
|
+
link_url = link_match[2].strip
|
|
237
|
+
|
|
238
|
+
if link_url.match?(/^https?:\/\//)
|
|
239
|
+
segments << {
|
|
240
|
+
type: 'text',
|
|
241
|
+
text: {
|
|
242
|
+
content: link_text,
|
|
243
|
+
link: { url: link_url }
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
elsif link_url.start_with?('#')
|
|
247
|
+
segments << {
|
|
248
|
+
type: 'text',
|
|
249
|
+
text: { content: link_text }
|
|
250
|
+
}
|
|
251
|
+
else
|
|
252
|
+
segments << {
|
|
253
|
+
type: 'text',
|
|
254
|
+
text: { content: link_text }
|
|
255
|
+
}
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
current_pos += link_match.begin(0) + link_match[0].length
|
|
259
|
+
else
|
|
260
|
+
remaining_text = text[current_pos..-1]
|
|
261
|
+
if remaining_text.length > 0
|
|
262
|
+
segments << {
|
|
263
|
+
type: 'text',
|
|
264
|
+
text: { content: remaining_text }
|
|
265
|
+
}
|
|
266
|
+
end
|
|
267
|
+
break
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
segments.empty? ? [{ type: 'text', text: { content: text } }] : segments
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
def is_table?(lines)
|
|
275
|
+
return false if lines.length < 2
|
|
276
|
+
return false unless lines[0].start_with?('|')
|
|
277
|
+
lines[1].match?(/^\|[\s:|-]+\|/)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def parse_table(lines)
|
|
281
|
+
table_lines = []
|
|
282
|
+
i = 0
|
|
283
|
+
|
|
284
|
+
while i < lines.length && lines[i].start_with?('|')
|
|
285
|
+
table_lines << lines[i]
|
|
286
|
+
i += 1
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
return [nil, 1] if table_lines.empty?
|
|
290
|
+
|
|
291
|
+
rows = table_lines.map { |line| parse_table_row(line) }
|
|
292
|
+
rows = rows.reject { |row| row.all? { |cell| cell.strip.match?(/^[-:|\s]*$/) } }
|
|
293
|
+
|
|
294
|
+
return [nil, i] if rows.empty?
|
|
295
|
+
|
|
296
|
+
table_width = rows.first.length
|
|
297
|
+
|
|
298
|
+
normalized_rows = rows.map do |row_cells|
|
|
299
|
+
normalized_cells = row_cells.dup
|
|
300
|
+
while normalized_cells.length < table_width
|
|
301
|
+
normalized_cells << ''
|
|
302
|
+
end
|
|
303
|
+
normalized_cells = normalized_cells[0...table_width] if normalized_cells.length > table_width
|
|
304
|
+
normalized_cells
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
table_rows = normalized_rows.map do |row_cells|
|
|
308
|
+
{
|
|
309
|
+
type: 'table_row',
|
|
310
|
+
table_row: {
|
|
311
|
+
cells: row_cells.map { |cell| [{ type: 'text', text: { content: cell.strip } }] }
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
block = {
|
|
317
|
+
type: 'table',
|
|
318
|
+
table: {
|
|
319
|
+
table_width: table_width,
|
|
320
|
+
has_column_header: true,
|
|
321
|
+
has_row_header: false,
|
|
322
|
+
children: table_rows
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
[block, i]
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def parse_table_row(line)
|
|
330
|
+
cells = line.split('|').map(&:strip)
|
|
331
|
+
cells = cells[1..-1] if cells.first.empty?
|
|
332
|
+
cells = cells[0..-2] if cells.last.empty?
|
|
333
|
+
cells
|
|
223
334
|
end
|
|
224
335
|
end
|
|
225
336
|
end
|
data/lib/synotion/version.rb
CHANGED