chat_sdk-teams 0.7.0 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26f507aa00b122a92a3b175ec79248a0cd4cf0d8a63d192ff5ada84eb8a4b307
4
- data.tar.gz: 54295b00effe5c4d7b37b906209dbcbb2685068da76eee7f3a68c020cdf391e9
3
+ metadata.gz: 2c1d10cccac3513f5852697594070029b0f106a6f1519110a54b865e26d58384
4
+ data.tar.gz: d707ebb3bf03165482bccf057873f0da94907259dc0f6d7d0b7292e5d080c66f
5
5
  SHA512:
6
- metadata.gz: aeac84b76ec10f316e3836676d85826d708b026293897ca7abfe77b3532af466519d2acc267ac41a21429d02af91feac58623ce40c6146eeda3f9fc35a204d56
7
- data.tar.gz: 3535fa1ecd603951f94d2df234f1fdc68239c66624cc0adf393be7def189168d910b377d8de1f6598178e60f94de5bdc05c1f630f9b3b35b2314540fa592bd59
6
+ metadata.gz: 51fb098edc33d6a63f33a713b9d5b157012fc2a24c5247c07127d9345d08bd083c24c83b3b4bbb998703bfbfd0d0288253c6a1cd53f85f89572277a23d1e03b9
7
+ data.tar.gz: 0edf7931855e4332b57cc8c70e32a4ae7ec4f081759e49cb2c5c399f014f5ac1baaf053ee4ffc3987dc4845c6eb8eec3953cdf13ab11130ea48a4026221cc402
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChatSDK
4
+ module Teams
5
+ class FormatConverter < ChatSDK::Format::Converter
6
+ # Teams HTML → Markdown
7
+ def to_markdown(platform_text)
8
+ text = platform_text.to_s
9
+ return "" if text.empty?
10
+
11
+ # Protect <pre> blocks first — extract them before processing inline HTML
12
+ pre_blocks = []
13
+ text = text.gsub(%r{<pre>(.*?)</pre>}mi) do
14
+ pre_blocks << Regexp.last_match(1)
15
+ "\x00PRE#{pre_blocks.size - 1}\x00"
16
+ end
17
+
18
+ # Protect <code> spans
19
+ code_spans = []
20
+ text = text.gsub(%r{<code>(.*?)</code>}mi) do
21
+ code_spans << Regexp.last_match(1)
22
+ "\x00CODE#{code_spans.size - 1}\x00"
23
+ end
24
+
25
+ # Convert block-level elements
26
+ text = convert_lists_to_markdown(text)
27
+
28
+ # Convert inline formatting
29
+ text = text.gsub(%r{<(?:b|strong)>(.*?)</(?:b|strong)>}mi, '**\1**')
30
+ text = text.gsub(%r{<(?:i|em)>(.*?)</(?:i|em)>}mi, '*\1*')
31
+ text = text.gsub(%r{<(?:s|strike|del)>(.*?)</(?:s|strike|del)>}mi, '~~\1~~')
32
+ text = text.gsub(%r{<a\s+href="([^"]*)"[^>]*>(.*?)</a>}mi, '[\2](\1)')
33
+ text = text.gsub(%r{<at>(.*?)</at>}mi, '@\1')
34
+ text = text.gsub(%r{<br\s*/?>}i, "\n")
35
+
36
+ # Decode HTML entities
37
+ text = decode_html_entities(text)
38
+
39
+ # Strip any remaining HTML tags
40
+ text = text.gsub(/<[^>]+>/, "")
41
+
42
+ # Restore code spans
43
+ code_spans.each_with_index do |content, i|
44
+ text = text.sub("\x00CODE#{i}\x00", "`#{content}`")
45
+ end
46
+
47
+ # Restore pre blocks
48
+ pre_blocks.each_with_index do |content, i|
49
+ text = text.sub("\x00PRE#{i}\x00", "```\n#{content}\n```")
50
+ end
51
+
52
+ text
53
+ end
54
+
55
+ # Markdown → Teams HTML
56
+ def from_markdown(markdown)
57
+ text = markdown.to_s
58
+ return "" if text.empty?
59
+
60
+ # Protect fenced code blocks first
61
+ code_blocks = []
62
+ text = text.gsub(/```\n?(.*?)\n?```/m) do
63
+ code_blocks << Regexp.last_match(1)
64
+ "\x00CODEBLOCK#{code_blocks.size - 1}\x00"
65
+ end
66
+
67
+ # Protect inline code spans
68
+ code_spans = []
69
+ text = text.gsub(/`([^`]+)`/) do
70
+ code_spans << Regexp.last_match(1)
71
+ "\x00CODESPAN#{code_spans.size - 1}\x00"
72
+ end
73
+
74
+ # Convert markdown formatting to HTML
75
+ text = text.gsub(/\*\*(.+?)\*\*/m, '<b>\1</b>')
76
+ text = text.gsub(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/m, '<i>\1</i>')
77
+ text = text.gsub(/~~(.+?)~~/m, '<s>\1</s>')
78
+ text = text.gsub(/\[([^\]]+)\]\(([^)]+)\)/, '<a href="\2">\1</a>')
79
+ text = text.gsub("\n", "<br>")
80
+
81
+ # Restore inline code spans
82
+ code_spans.each_with_index do |content, i|
83
+ text = text.sub("\x00CODESPAN#{i}\x00", "<code>#{content}</code>")
84
+ end
85
+
86
+ # Restore code blocks
87
+ code_blocks.each_with_index do |content, i|
88
+ text = text.sub("\x00CODEBLOCK#{i}\x00", "<pre>#{content}</pre>")
89
+ end
90
+
91
+ text
92
+ end
93
+
94
+ private
95
+
96
+ def convert_lists_to_markdown(html)
97
+ # Convert unordered lists
98
+ html = html.gsub(%r{<ul>(.*?)</ul>}mi) do
99
+ items = Regexp.last_match(1)
100
+ items.gsub(%r{<li>(.*?)</li>}mi) { "- #{Regexp.last_match(1).strip}\n" }.strip
101
+ end
102
+
103
+ # Convert ordered lists
104
+ html.gsub(%r{<ol>(.*?)</ol>}mi) do
105
+ items = Regexp.last_match(1)
106
+ index = 0
107
+ items.gsub(%r{<li>(.*?)</li>}mi) do
108
+ index += 1
109
+ "#{index}. #{Regexp.last_match(1).strip}\n"
110
+ end.strip
111
+ end
112
+ end
113
+
114
+ def decode_html_entities(text)
115
+ text
116
+ .gsub("&amp;", "&")
117
+ .gsub("&lt;", "<")
118
+ .gsub("&gt;", ">")
119
+ .gsub("&quot;", '"')
120
+ .gsub("&#39;", "'")
121
+ .gsub("&nbsp;", " ")
122
+ end
123
+ end
124
+ end
125
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chat_sdk-teams
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Quentin Rousseau
@@ -63,6 +63,7 @@ files:
63
63
  - lib/chat_sdk/teams/adapter.rb
64
64
  - lib/chat_sdk/teams/adaptive_card_renderer.rb
65
65
  - lib/chat_sdk/teams/bot_framework_client.rb
66
+ - lib/chat_sdk/teams/format_converter.rb
66
67
  - lib/chat_sdk/teams/graph_client.rb
67
68
  - lib/chat_sdk/teams/jwt_verifier.rb
68
69
  homepage: https://github.com/rootlyhq/chat-sdk