me2text-ruby 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ .yardoc
4
+ Gemfile.lock
5
+ doc/*
6
+ pkg/*
7
+ perf/*
8
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in me2text-ruby.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2006-2012 NHN Corp.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ me2text-ruby, me2text parser for ruby
2
+ ======================================
3
+
4
+ me2text-ruby는 me2text 형식의 문자열을 HTML 또는 평문(plain text)로 변환해주는
5
+ ruby 라이브러리이다.
6
+
7
+ 사용
8
+ ----
9
+
10
+ ### HTML로 변환
11
+
12
+ require 'me2text'
13
+
14
+ str = 'me2text는 "미투데이(TM)":http://me2day.net 의 글/댓글 작성 규칙이다.'
15
+ Me2Text.me2text(str)
16
+ # => me2text는 <a href='http://me2day.net'>미투데이™"</a>의 글/댓글 작성 규칙이다.
17
+
18
+ ### 평문으로 변환
19
+
20
+ require 'me2text'
21
+
22
+ str = 'me2text는 "미투데이(TM)":http://me2day.net 의 글/댓글 작성 규칙이다.'
23
+ Me2Text.me2text(str, :text)
24
+ # => me2text는 미투데이™"의 글/댓글 작성 규칙이다.
25
+
26
+ ### String 클래스 확장
27
+
28
+ require 'me2text/string_ext'
29
+
30
+ str = 'me2text는 "미투데이(TM)":http://me2day.net 의 글/댓글 작성 규칙이다.'
31
+ str.me2text
32
+ # => me2text는 <a href='http://me2day.net'>미투데이™"</a>의 글/댓글 작성 규칙이다.
33
+
34
+ ### 주의 사항
35
+
36
+ me2text-ruby 사용을 위해서는 $KCODE 변수를 'UTF8' 또는 'u'로 지정해야 한다.
37
+
38
+ $KCODE = 'UTF8'
39
+
40
+ me2text-ruby는 ruby 1.8.7-p302에서 테스트되었으며 아직 ruby 1.9.X를 지원하지 않는다.
41
+
42
+ 설치
43
+ ----
44
+ me2text-ruby 라이브러리는 RubyGems를 통해 설치할 수 있다.
45
+
46
+ gem install me2text-ruby
47
+
48
+
49
+ me2text란?
50
+ ----------
51
+ me2text는 미투데이 글/댓글등의 글 작성 규칙을 일컫는다.
52
+
53
+ ### 링크
54
+
55
+ 링크를 표현하는 형식은 다음과 같다
56
+
57
+ "링크를 걸 문구":URL
58
+
59
+ 예를 들면 다음과 같다.
60
+
61
+ 미투텍스트는 "미투데이":http://me2day.net 의 글/댓글 작성 규칙을 일컫는다.
62
+ => 미투텍스트는 <a href='http://me2day.net'>미투데이"</a>의 글/댓글 작성 규칙을 일컫는다.
63
+
64
+ 또, 이와 같은 링크 형식으로 작성되지 않더라도 단순히 URL만 지정한 경우에 대해서도 링크로
65
+ 변환한다.
66
+
67
+ `자세한 내용은 이 주소로. http://me2day.net`
68
+ => `자세한 내용은 이 주소로. <a href='http://me2day.net'>http://me2day.net</a>`
69
+
70
+ 백슬래시를 사용해 링크를 걸 문구에 따옴표를 포함할 수 있다. 즉, 아래와 같은 링크를 지정한
71
+ 문자열에서 링크를 걸 문구에 포함된 따옴표에는 백슬래시를 붙여 전체 문자열에 링크를 적용할
72
+ 수 있다.
73
+
74
+ "레이디가가 소감, \"한국의 환대 따뜻하고 신나, 그리웠다\"":http://me2.do/FnlH8u3
75
+ => <a href='http://me2.do/FnlH8u3'>레이디가가 소감, “한국의 환대 따뜻하고 신나, 그리웠다”</a>
76
+
77
+ ### 따옴표
78
+
79
+ 다음과 같이 따옴표 문자를 LEFT/RIGHT DOUBLE QUOTATION MARK(“”) 문자로 변환한다.
80
+
81
+ "안녕하세요" -> “안녕하세요”
82
+
83
+ ### 심볼 문자의 표현
84
+
85
+ 다음과 같은 특정 순서의 문자열을 심볼 문자로 변환한다.
86
+
87
+ * ... => … (HORIZONTAL ELLIPSIS)
88
+ * (TM) => ™ (TRADE MARK SIGN)
89
+ * (R) => ® (REGISTERED SIGN)
90
+ * (C) => © (COPYRIGHT SIGN)
91
+ * -- => — (EN DASH)
92
+
93
+ TODO
94
+ ----
95
+
96
+ * Ruby 1.9 지원
97
+
98
+ Copyright and License
99
+ ---------------------
100
+
101
+ Copyright 2012 NHN Corp.
102
+
103
+ me2text is released under the MIT license:
104
+
105
+ * www.opensource.org/licenses/MIT
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,108 @@
1
+ # encoding: utf-8
2
+
3
+ require 'me2text/token'
4
+
5
+ # Public: me2text 변환 메소드 제공한다.
6
+ #
7
+ # Examples
8
+ #
9
+ # require 'me2text'
10
+ #
11
+ # str = 'me2text는 "미투데이(TM)":http://me2day.net 의 글/댓글 작성 규칙이다.'
12
+ # Me2Text.me2text(str)
13
+ # # => me2text는 <a href='http://me2day.net'>미투데이™"</a>의 글/댓글 작성 규칙이다.
14
+ module Me2Text
15
+ class << self
16
+ # me2text(`text`)를 HTML로 변환한다.
17
+ #
18
+ # text - 변환할 me2text 형식의 문자열
19
+ # options - 다음과 같은 옵션을 지원한다. :
20
+ # :symbolize - 특정 순서의 문자열을 UNICODE의 해당 심볼로 변환한다.
21
+ # 지정하지 않는 경우 `true`.
22
+ # :open_new_window - +:html+ 형식으로 변환시 link에 대해 클릭하면 새 창으로 열릴
23
+ # 수 있도록 `<a>` 태그에 `target='_blank'`를 삽입한다.
24
+ # 지정하지 않는 경우 `false`.
25
+ # :allow_line_break - 라인브레이크를 허용한다. `:html` 로 변환시 라인브레이크는
26
+ # `<br />` 태그로 변환된다. 지정하지 않는 경우 `false`.
27
+ # :limit - 변환 결과의 글자수를 제한한다. `:limit`에는 숫자를 지정하며 변환 결과는
28
+ # 지정된 글자 수 까지만 변환된다.
29
+ # :link_handler - 문자열에 나타나는 각 링크에 대해 지정된 block이 호출된다.
30
+ def to_html(text, options = {})
31
+ me2text(text, :html, options)
32
+ end
33
+
34
+ # me2text(+text+)를 평문(plain text)로 변환한다.
35
+ #
36
+ # text - 변환할 me2text 형식의 문자열
37
+ # options - 다음과 같은 옵션을 지원한다. :
38
+ # :symbolize - 특정 순서의 문자열을 UNICODE의 해당 심볼로 변환한다.
39
+ # 지정하지 않는 경우 `true`.
40
+ # :allow_line_break - 라인브레이크를 허용한다. `:html` 로 변환시 라인브레이크는
41
+ # `<br />` 태그로 변환된다. 지정하지 않는 경우 `false`.
42
+ # :limit - 변환 결과의 글자수를 제한한다. `:limit`에는 숫자를 지정하며 변환 결과는
43
+ # 지정된 글자 수 까지만 변환된다.
44
+ # :link_handler - 문자열에 나타나는 각 링크에 대해 지정된 block이 호출된다.
45
+ def to_text(text, options = {})
46
+ me2text(text, :text, options)
47
+ end
48
+
49
+ # me2text(`text`)를 지정한 형식(`format`)으로 변환한다.
50
+ #
51
+ # text - 변환할 me2text 형식의 문자열
52
+ # format - 변환 형식을 지정한다. `:html`, `:text` 중 하나를 지정하며
53
+ # 지정하지 않은 경우 +:html+ 이 지정된다. `:html`은 HTML 형식으로 변환하며
54
+ # +:text+는 평문(plain text)으로 변환한다.
55
+ # options - 다음과 같은 옵션을 지원한다. :
56
+ # :symbolize - 특정 순서의 문자열을 UNICODE의 해당 심볼로 변환한다.
57
+ # 지정하지 않는 경우 `true`.
58
+ # :open_new_window - +:html+ 형식으로 변환시 link에 대해 클릭하면 새 창으로 열릴
59
+ # 수 있도록 `<a>` 태그에 `target='_blank'`를 삽입한다.
60
+ # 지정하지 않는 경우 `false`.
61
+ # :allow_line_break - 라인브레이크를 허용한다. `:html` 로 변환시 라인브레이크는
62
+ # `<br />` 태그로 변환된다. 지정하지 않는 경우 `false`.
63
+ # :limit - 변환 결과의 글자수를 제한한다. `:limit`에는 숫자를 지정하며 변환 결과는
64
+ # 지정된 글자 수 까지만 변환된다.
65
+ # :link_handler - 문자열에 나타나는 각 링크에 대해 지정된 block이 호출된다.
66
+ def me2text(text, format = :html, options = {})
67
+ options = {
68
+ :symbolize => true,
69
+ :open_new_window => false,
70
+ :allow_line_break => false,
71
+ :limit => nil,
72
+ :link_handler => nil
73
+ }.merge(options)
74
+ text = strip_linebreak(text) unless options[:allow_line_break]
75
+
76
+ text = Token.join_tokens(Token.tokenize(text), format, options)
77
+
78
+ # 키워드 핸들러 등록시, doublequote 가 결과에 포함되어 있는 경우
79
+ # doublequotize 메소드가 마지막에 호출 됨으로 에러 발생한다.
80
+ text = doublequotize(text) if options[:symbolize]
81
+
82
+ if format == :html
83
+ text = htmlize_linebreak(text) if options[:allow_line_break]
84
+ end
85
+
86
+ strip_control_chars(text)
87
+ end
88
+
89
+ def doublequotize(text) #:nodoc:
90
+ text.gsub(/\"([^"]*)\"/) { |s| "“#{$1}”" }
91
+ end
92
+
93
+ # 라인브레이크를 <br /> 태그로 대체한다.
94
+ def htmlize_linebreak(text)
95
+ text.gsub(/\r\n/, "<br />").gsub(/\n/, "<br />").gsub(/\r/, "<br />")
96
+ end
97
+
98
+ # 컨트롤 문자를 제거한다.
99
+ def strip_control_chars(text)
100
+ text.gsub(/[[:cntrl:]]/, "")
101
+ end
102
+
103
+ # 라인브래이크를 공백으로 변환한다
104
+ def strip_linebreak(text)
105
+ text.gsub(/\s\r\n/, "").gsub(/\r\n/, " ").gsub(/[\r\n]/, " ")
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,26 @@
1
+ require 'me2text'
2
+
3
+ module Me2Text
4
+ module StringExtension
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ base.send(:include, InstanceMethods)
8
+ end
9
+
10
+ module InstanceMethods
11
+ def me2text(format = :html, options = {})
12
+ Me2Text.me2text(self, format, options)
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+ def me2text(text, format = :html, options = {})
18
+ Me2Text.me2text(text, format, options)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ class String
25
+ include Me2Text::StringExtension
26
+ end
@@ -0,0 +1,345 @@
1
+ # encoding: utf-8
2
+
3
+ module Me2Text
4
+ class Token
5
+ REGEX_ME2LINK = begin
6
+ dquota_s = '\\xe2\\x80\\x9c|\\xe2\\x80\\x9f|\\xe2\\x9d\\x9d|\\xe2\\x80\\xb6|\\xe2\\x80\\x9d|\\x22|\\xef\\xbc\\x82'
7
+ dquota_e = '\\xe2\\x80\\x9d|\\xe2\\x80\\x9e|\\xe2\\x9d\\x9e|\\xcb\\x9d|\\xe2\\x80\\xb3|\\xe2\\x80\\x9e|\\xe2\\x80\\x9f|\\x22|\\xef\\xbc\\x82'
8
+ dquota_ne = '\\xe2\\x80\\x9d\\xe2\\x80\\x9e\\xe2\\x9d\\x9e\\xcb\\x9d\\xe2\\x80\\xb3\\xe2\\x80\\x9e\\xe2\\x80\\x9f\\x22\\xef\\xbc\\x82'
9
+ /(?:#{dquota_s})([^#{dquota_ne}]*)(?:#{dquota_e}):(http[s]?:\/\/[^\s]*)(\s|$)/
10
+ end
11
+ REGEX_URL = /(http[s]?:\/\/[^\s|^\'|^\"]*)([\'|\"|\s]|$)/
12
+ ESCAPE_CHAR = "\xc2\xa0"
13
+
14
+ attr_accessor :text
15
+
16
+ def to_s(format, options = {})
17
+ unless [:html, :text].include?(format)
18
+ raise ArgumentError.new("Unknown format: #{format.inspect}")
19
+ end
20
+ self.send('to_' + format.to_s, options)
21
+ end
22
+
23
+ def to_html(options ={})
24
+ end
25
+
26
+ def to_text(options ={})
27
+ end
28
+
29
+ def length(options ={})
30
+ 1
31
+ end
32
+
33
+ def truncate(nos, format, options = {})
34
+ options = {
35
+ :ellipsis => "…"
36
+ }.merge(options)
37
+
38
+ [options[:ellipsis], 1]
39
+ end
40
+
41
+ protected
42
+
43
+ def htmlize(text, options = {})
44
+ options = {
45
+ :symbolize => true,
46
+ :linklize_class => "write_link"
47
+ }.merge(options)
48
+
49
+ remain = text
50
+ result = ""
51
+ if options[:linklize]
52
+ while (m = remain.match(REGEX_URL))
53
+ url = m[1]
54
+ after_url = m[2]
55
+
56
+ result << htmlize_chars(m.pre_match, options) if !m.pre_match.empty?
57
+ result << "<a href='#{url.to_s.strip}'"
58
+ result << " class='#{options[:linklize_class]}'" if options[:linklize_class]
59
+ result << " target='_blank'" if options[:open_new_window]
60
+ result << ">"
61
+ result << url
62
+ result << "</a>"
63
+ result << after_url
64
+
65
+ remain = m.post_match
66
+ end
67
+ end
68
+ result << htmlize_chars(remain, options)
69
+
70
+ result
71
+ end
72
+
73
+ def htmlize_chars(text, options = {})
74
+ html_result = text.to_s.gsub(/&/, "&amp;").gsub(/</, "&lt;").gsub(/>/, "&gt;")
75
+ html_result = textize(html_result, options)
76
+ html_result
77
+ end
78
+
79
+ def textize(text, options = {})
80
+ options = {
81
+ :symbolize => true
82
+ }.merge(options)
83
+
84
+ if options[:symbolize]
85
+ text = text.gsub(/\.\.\./, "…").
86
+ gsub(/\(TM\)/, "™").
87
+ gsub(/\(R\)/, "®").
88
+ gsub(/\(C\)/, "©").
89
+ gsub(/--/, "—")
90
+ end
91
+ text
92
+ end
93
+
94
+ class << self
95
+ def tokenize(text, options = {})
96
+ tokenize_me2link(text.gsub(/\\\"/, ESCAPE_CHAR), options)
97
+ end
98
+
99
+ def tokenize_me2link(text, options = {})
100
+ tokens = []
101
+ while (m = text.match(REGEX_ME2LINK))
102
+ # 매치 이전 텍스트 처리
103
+ tokens += tokenize_keyword(m.pre_match, options) if !m.pre_match.empty?
104
+
105
+ url = m[2]
106
+ anchor_text = m[1]
107
+ if url
108
+ if !options[:link_handler].nil?
109
+ url = options[:link_handler].call(url, options)
110
+ end
111
+ tokens << Link.new(anchor_text, url, m[3].length > 0)
112
+ else
113
+ tokens += tokenize_keyword(anchor_text, options)
114
+ end
115
+
116
+ text = m.post_match
117
+ end
118
+ if !text.empty?
119
+ tokens += tokenize_keyword(text, options)
120
+ end
121
+
122
+ tokens
123
+ end
124
+
125
+ def tokenize_keyword(text, options = {})
126
+ tokens = []
127
+ while (m = text.match(Keyword::KEYWORD_REGEX))
128
+ tokens += tokenize_plaintext(m.pre_match, options) if !m.pre_match.empty?
129
+ tokens << Keyword.new(m.to_s, options)
130
+ text = m.post_match
131
+ end
132
+ if !text.empty?
133
+ tokens += tokenize_plaintext(text, options)
134
+ end
135
+
136
+ tokens
137
+ end
138
+
139
+ def tokenize_plaintext(text, options = {})
140
+ [Plain.new(text)]
141
+ end
142
+
143
+ def join_tokens(tokens, format, options)
144
+ if options[:limit].nil?
145
+ return tokens.map { |token| token.to_s(format, options) }.join
146
+ end
147
+
148
+ result = ""
149
+ process_length = 0
150
+ tokens.each_with_index do |tk, idx|
151
+ n_len = process_length + tk.length
152
+ r_len = length - n_len
153
+
154
+ # 길이가 남았다.
155
+ if r_len > 0
156
+ process_length = process_length + tk.length
157
+ result << tk.to_s(format, options)
158
+
159
+ # 길이가 딱 맞다.
160
+ elsif r_len == 0
161
+ # 이번 토큰이 마지막 토큰(더이상 추가할 게 없음) 인가?
162
+ if (idx + 1) == tokens.size
163
+ process_length = process_length + tk.length
164
+ result << tk.to_s(format, options)
165
+ else
166
+ # 남은 문자열이 있다.
167
+ val = tk.truncate(0, format, options)
168
+ process_length = process_length + val[1]
169
+ result << val.first
170
+ end
171
+ break
172
+
173
+ # 길이가 r_len만큼 모자르다
174
+ else
175
+ val = tk.truncate(-r_len, format, options)
176
+ process_length = process_length + val[1]
177
+ result << val.first
178
+ break
179
+ end
180
+ end
181
+
182
+ result
183
+ end
184
+ end
185
+ end
186
+
187
+ class Plain < Token
188
+ def initialize(tv)
189
+ @text = tv.gsub(ESCAPE_CHAR, "\"")
190
+ end
191
+
192
+ def to_html(options = {})
193
+ htmlize(@text, options)
194
+ end
195
+
196
+ def to_text(options = {})
197
+ textize(@text, options)
198
+ end
199
+
200
+ def length
201
+ @text.split(//u).length
202
+ end
203
+
204
+ def truncate(nos, format, options = {})
205
+ options = {
206
+ :ellipsis => "…"
207
+ }.merge(options)
208
+
209
+ val = self.to_s(format, options)
210
+ if (val.length - nos) <= 0
211
+ #빼면 아무것도 없다면..
212
+ ##이 링크는 버린다
213
+ options[:ellipsis]
214
+ else
215
+ val = val.split(//u)[0...(val.length - nos) - 1]
216
+ val << options[:ellipsis]
217
+ end
218
+
219
+ @text = val
220
+
221
+ [val, length]
222
+ end
223
+ end
224
+
225
+ class Link < Token
226
+ attr_accessor :link
227
+ attr_accessor :include_ws
228
+
229
+ def initialize(label, link, include_ws = false)
230
+ @text = label.gsub(ESCAPE_CHAR, "\"")
231
+ @link = link.gsub("'","%27").gsub("\"","%22").gsub("<", "%3C").gsub(">", "%3E")
232
+ @include_ws = include_ws
233
+ end
234
+
235
+ def to_label(format,options = {})
236
+ options = options.merge({
237
+ :linklize => false
238
+ })
239
+
240
+ result = if format == :html
241
+ htmlize(@text, options)
242
+ elsif format == :text
243
+ textize(@text, options)
244
+ else
245
+ @text
246
+ end
247
+
248
+ if result.strip.length == 0
249
+ if format == :html
250
+ result = htmlize(" " + link + " ",options)
251
+ elsif format == :text
252
+ result = textize(" " + link + " " ,options)
253
+ else
254
+ @text
255
+ end
256
+ end
257
+
258
+ return result
259
+ end
260
+
261
+ def to_html(options = {})
262
+ if options[:open_new_window]
263
+ "<a href='#{link}' target='_blank'>#{to_label(:html,options)}</a>"
264
+ else
265
+ "<a href='#{link}'>#{to_label(:html,options)}</a>"
266
+ end
267
+ end
268
+
269
+ def to_text(options = {})
270
+ to_label(:text, options)
271
+ end
272
+
273
+ def length(options = {})
274
+ textize(@text,options).length
275
+ end
276
+
277
+ def truncate(nos, format, options = {})
278
+ options = {
279
+ :ellipsis => "…"
280
+ }.merge(options)
281
+
282
+ val = self.to_label(format,options)
283
+ if (val.length - nos) <= 0
284
+ #빼면 아무것도 없다면..
285
+ ##이 링크는 버린다
286
+ options[:ellipsis]
287
+ else
288
+ val = val.split(//u)[0...(val.length-nos) - 1]
289
+ val << options[:ellipsis]
290
+ end
291
+
292
+ @text= val
293
+ [to_s(format,options), length(options)]
294
+ end
295
+ end
296
+
297
+ class Keyword < Token
298
+ KEYWORD_REGEX = /(\[([^\[\]]+)\])/
299
+ attr_accessor :link
300
+
301
+ def initialize(keyword, options)
302
+ # keyword는 "[키워드]" 같은 형태
303
+ _keyword = keyword.to_s.strip.scan(KEYWORD_REGEX)
304
+ _keyword = _keyword.flatten[1]
305
+
306
+ raise "키워드가 없습니다." if _keyword.nil?
307
+
308
+ @text = _keyword.gsub(ESCAPE_CHAR, "\"")
309
+ end
310
+
311
+ def to_html(options = {})
312
+ if options[:keyword_handler] && options[:keyword_handler].is_a?(Proc)
313
+ options[:keyword_handler].call(@text, options)
314
+ else
315
+ "[#{htmlize(@text, options)}]"
316
+ end
317
+ end
318
+
319
+ def to_text(options = {})
320
+ "[#{textize(@text, options)}]"
321
+ end
322
+
323
+ def length(options = {})
324
+ textize(@text, options).length
325
+ end
326
+
327
+ def truncate(nos, format, options = {})
328
+ options = {
329
+ :ellipsis => "…"
330
+ }.merge(options)
331
+
332
+ val = self.to_text(options)
333
+ if (val.length - nos) <= 0
334
+ # 빼면 아무것도 없다면 이 링크는 버린다
335
+ options[:ellipsis]
336
+ else
337
+ val = val.split(//u)[0...(val.length - nos) - 1]
338
+ val << options[:ellipsis]
339
+ end
340
+
341
+ @text = val
342
+ [to_s(format, options), length(options)]
343
+ end
344
+ end
345
+ end
@@ -0,0 +1,3 @@
1
+ module Me2Text
2
+ VERSION = "1.0.0"
3
+ end
data/lib/me2text.rb ADDED
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+
3
+ major, minor, patch = RUBY_VERSION.split('.')
4
+ if major.to_i == 1 && minor.to_i > 8
5
+ raise("me2text는 ruby 1.9 이상은 현재 지원하지 않습니다.")
6
+ else
7
+ # Ruby 1.8 $KCODE check.
8
+ unless $KCODE[0].chr =~ /u/i
9
+ raise("me2text를 사용하기 위해서는 $KCODE 변수를 'UTF8' 또는 'u'로 지정해야 합니다.")
10
+ end
11
+ end
12
+
13
+ $:.push(File.expand_path("..", __FILE__))
14
+
15
+ module Me2Text
16
+ end
17
+
18
+ require 'me2text/version'
19
+ require 'me2text/me2text'
20
+
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "me2text/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "me2text-ruby"
7
+ s.version = Me2Text::VERSION
8
+ s.authors = ["codian"]
9
+ s.email = ["codian@gmail.com"]
10
+ s.homepage = "http://me2day.net"
11
+ s.summary = %q{me2text parser for ruby}
12
+ s.description = %q{me2text is text format for me2day posting.
13
+ me2text-ruby is ruby library to me2text to HTML or plain text}
14
+ s.rubyforge_project = "me2text-ruby"
15
+ s.files = Dir['{lib/**/*,test/**/*}'] +
16
+ %w(.gitignore me2text-ruby.gemspec Gemfile MIT-LICENSE Rakefile README.md)
17
+ s.test_files = Dir['test/**/*']
18
+ s.executables = ''
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "rspec"
23
+ # s.add_runtime_dependency "rest-client"
24
+ end
data/test/test.rb ADDED
@@ -0,0 +1,64 @@
1
+ # encoding: utf-8
2
+
3
+ require File.expand_path('../test_helper', __FILE__)
4
+
5
+ class Me2TextTest < Test::Unit::TestCase
6
+ def test_to_html
7
+ cases = [
8
+ # 일반 텍스트
9
+ ['안녕하세요. 미투데이입니다.', '안녕하세요. 미투데이입니다.'],
10
+ ['"안녕하세요." 미투데이입니다.', '“안녕하세요.” 미투데이입니다.'],
11
+ ['안녕하세요...(C)(R)(TM)-- 미투데이입니다', "안녕하세요…©®™— 미투데이입니다"],
12
+
13
+ # html 이스케이프
14
+ ['안녕하세요. <br /> 미투데이입니다.', '안녕하세요. &lt;br /&gt; 미투데이입니다.'],
15
+ ['안녕하세요. &nbsp;미투데이입니다.', '안녕하세요. &amp;nbsp;미투데이입니다.'],
16
+
17
+ # 링크 문법
18
+ ['"안녕하세요":http://me2day.net . 미투데이입니다.', '<a href=\'http://me2day.net\'>안녕하세요</a>. 미투데이입니다.'],
19
+ ['안녕"하세요":http://me2day.net . 미투데이입니다.', '안녕<a href=\'http://me2day.net\'>하세요</a>. 미투데이입니다.'],
20
+ ['안녕하세요. "미투데이입니다.":http://me2day.net', '안녕하세요. <a href=\'http://me2day.net\'>미투데이입니다.</a>'],
21
+
22
+ # 키워드 문법
23
+ ['[안녕하세요]. 미투데이입니다.', '[안녕하세요]. 미투데이입니다.'],
24
+
25
+ # 따옴표 이스케이프한 경우
26
+ ['"\\"안녕하세요\\"":http://me2day.net . 미투데이입니다.', '<a href=\'http://me2day.net\'>“안녕하세요”</a>. 미투데이입니다.'],
27
+
28
+ # 컨트롤 문자 strip
29
+ ["\000안녕하세요. 미투데이입니다.", '안녕하세요. 미투데이입니다.']
30
+ ]
31
+
32
+ cases.each_with_index do |test, index|
33
+ text = test[0]
34
+ expect = test[1]
35
+ result = Me2Text.me2text(text, :html)
36
+ if expect != result
37
+ flunk "TEXT: #{text}\n" +
38
+ "EXPECT: #{expect}\n" +
39
+ "RESULT: #{result}\n"
40
+ end
41
+ end
42
+ end
43
+
44
+ def test_strip_linebreak
45
+ cases = [
46
+ ["안녕하세요.\n미투데이입니다.", '안녕하세요.<br />미투데이입니다.'],
47
+ ["안녕하세요.\r미투데이입니다.", '안녕하세요.<br />미투데이입니다.'],
48
+ ["안녕하세요.\r\n미투데이입니다.", '안녕하세요.<br />미투데이입니다.'],
49
+ ["안녕하세요.\n\r미투데이입니다.", '안녕하세요.<br /><br />미투데이입니다.'],
50
+ ]
51
+
52
+ cases.each_with_index do |test, index|
53
+ text = test[0]
54
+ expect = test[1]
55
+ result = Me2Text.me2text(text, :html, :allow_line_break => true)
56
+ if expect != result
57
+ flunk "TEXT: #{text.inspect}\n" +
58
+ "EXPECT: #{expect}\n" +
59
+ "RESULT: #{result}\n"
60
+ end
61
+ end
62
+ end
63
+ end
64
+
@@ -0,0 +1,9 @@
1
+ # encoding: utf-8
2
+
3
+ major, minor, patch = RUBY_VERSION.split('.')
4
+ $KCODE = "U" if major.to_i == 1 && minor.to_i < 9
5
+
6
+ require 'test/unit'
7
+ require File.expand_path('../../lib/me2text', __FILE__)
8
+
9
+
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: me2text-ruby
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - codian
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-21 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: |-
22
+ me2text is text format for me2day posting.
23
+ me2text-ruby is ruby library to me2text to HTML or plain text
24
+ email:
25
+ - codian@gmail.com
26
+ executables: []
27
+
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - lib/me2text/me2text.rb
34
+ - lib/me2text/string_ext.rb
35
+ - lib/me2text/token.rb
36
+ - lib/me2text/version.rb
37
+ - lib/me2text.rb
38
+ - test/test.rb
39
+ - test/test_helper.rb
40
+ - .gitignore
41
+ - me2text-ruby.gemspec
42
+ - Gemfile
43
+ - MIT-LICENSE
44
+ - Rakefile
45
+ - README.md
46
+ homepage: http://me2day.net
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options: []
51
+
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ hash: 3
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ requirements: []
73
+
74
+ rubyforge_project: me2text-ruby
75
+ rubygems_version: 1.8.23
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: me2text parser for ruby
79
+ test_files:
80
+ - test/test.rb
81
+ - test/test_helper.rb
82
+ has_rdoc: