tdiary-style-markdown 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # TDiary::Style::Markdown
2
+
3
+ "Markdown" style for tDiary 2.x format.
4
+
5
+ This is based on tdiary-style-gfm gem.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'tdiary-style-markdown'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install tdiary-style-markdown
20
+
21
+ ## Usage
22
+
23
+ if you want to use this style, add @style into tdiary.conf below:
24
+
25
+ @style = 'Markdown'
26
+
27
+ ## Contributing
28
+
29
+ 1. Fork it
30
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
31
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
32
+ 4. Push to the branch (`git push origin my-new-feature`)
33
+ 5. Create new Pull Request
34
+
35
+ ## Copyright
36
+
37
+ * Copyright (C) 2003, TADA Tadashi <sho@spc.gr.jp>
38
+ * Copyright (C) 2004, MoonWolf <moonwolf@moonwolf.com>
39
+ * Copyright (C) 2012, kdmsnr <kdmsnr@gmail.com>
40
+ * Copyright (C) 2013, hsbt <shibata.hiroshi@gmail.com>
41
+ * Copyright (C) 2015, Kenji Okimoto <okimoto@clear-code.com>
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ module TDiary
2
+ module Style
3
+ module Markdown
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,208 @@
1
+ require 'redcarpet'
2
+ require 'pygments'
3
+ require 'twitter-text'
4
+
5
+ module TDiary
6
+ module Style
7
+ class MarkdownSection
8
+ def initialize(fragment, author = nil)
9
+ @author = author
10
+ @subtitle, @body = fragment.split(/\n/, 2)
11
+ @subtitle.sub!(/^\#\s*/,'')
12
+ @body ||= ''
13
+
14
+ @categories = get_categories
15
+ @stripped_subtitle = strip_subtitle
16
+
17
+ @subtitle_to_html = @subtitle ? to_html('# ' + @subtitle).gsub(/\A<h\d>|<\/h\d>\z/io, '') : nil
18
+ @stripped_subtitle_to_html = @stripped_subtitle ? to_html('# ' + @stripped_subtitle).gsub(/\A<h\d>|<\/h\d>\z/io, '') : nil
19
+ @body_to_html = to_html(@body)
20
+ end
21
+
22
+ def subtitle=(subtitle)
23
+ @subtitle = (subtitle || '').sub(/^# /,"\##{categories_to_string} ")
24
+ @strip_subtitle = strip_subtitle
25
+ end
26
+
27
+ def categories=(categories)
28
+ @subtitle = "#{categories_to_string} " + (strip_subtitle || '')
29
+ @strip_subtitle = strip_subtitle
30
+ end
31
+
32
+ def to_src
33
+ r = ''
34
+ r << "\# #{@subtitle}\n" if @subtitle
35
+ r << @body
36
+ end
37
+
38
+ def do_html4(date, idx, opt)
39
+ subtitle = to_html('# ' + @subtitle)
40
+ subtitle.sub!( %r!<h3>(.+?)</h3>!m ) do
41
+ "<h3><%= subtitle_proc( Time.at( #{date.to_i} ), #{$1.dump.gsub( /%/, '\\\\045' )} ) %></h3>"
42
+ end
43
+ if opt['multi_user'] and @author then
44
+ subtitle.sub!(/<\/h3>/,%Q|[#{@author}]</h3>|)
45
+ end
46
+ r = subtitle
47
+ r << @body_to_html
48
+ end
49
+
50
+ private
51
+
52
+ def to_html(string)
53
+ r = string.dup
54
+
55
+ # 1. Stash plugin calls
56
+ plugin_stashes = []
57
+ r.gsub!(/\{\{(.*?)\}\}/) do |matched|
58
+ # Convert `{{ }}' to erb tags
59
+ plugin_stashes.push([matched, "<%=#{$1}%>"])
60
+ "@@tdiary-style-markdown-plugin#{plugin_stashes.length - 1}@@"
61
+ end
62
+
63
+ # 2. Apply markdown conversion
64
+ renderer = Redcarpet::Markdown.new(HTMLwithPygments,
65
+ fenced_code_blocks: true,
66
+ tables: true,
67
+ autolink: true,
68
+ footnotes: true)
69
+ r = renderer.render(r)
70
+
71
+ # 3. Stash <pre> and <code> tags
72
+ pre_tag_stashes = []
73
+ r.gsub!(/<pre(.*?)<\/pre>/m) do |matched|
74
+ pre_tag_stashes.push(matched)
75
+ "@@tdiary-style-markdown-pre_tag#{pre_tag_stashes.length - 1}@@"
76
+ end
77
+
78
+ code_tag_stashes = []
79
+ r.gsub!(/<code(.*?)<\/code>/m) do |matched|
80
+ code_tag_stashes.push(matched)
81
+ "@@tdiary-style-markdown-code_tag#{code_tag_stashes.length - 1}@@"
82
+ end
83
+
84
+ # 4. Convert miscellaneous
85
+ if pre_tag_stashes.none? && code_tag_stashes.none?
86
+ r = Twitter::Autolink.auto_link_usernames_or_lists(r)
87
+ end
88
+
89
+ r = r.emojify
90
+
91
+ # diary anchor
92
+ r.gsub!(/<h(\d)/) { "<h#{$1.to_i + 2}" }
93
+ r.gsub!(/<\/h(\d)/) { "</h#{$1.to_i + 2}" }
94
+
95
+ # my syntax
96
+ r.gsub!(/<a href="(\d{4}|\d{6}|\d{8}|\d{8}-\d+)[^\d]*?#?([pct]\d+)?">(.*?)<\/a>/) {
97
+ unless $3.empty?
98
+ %Q|<%=my "#{$1}#{$2}", "#{$3}" %>|
99
+ else
100
+ %Q|<%=my "#{$1}#{$2}", "#{$1}#{$2}" %>|
101
+ end
102
+ }
103
+
104
+ # 5. Unstash <pre>, <code> and plugin call
105
+ pre_tag_stashes.each.with_index do |str, i|
106
+ plugin_stashes.each.with_index do |(p_str, p_erb), j|
107
+ if str["@@tdiary-style-markdown-plugin#{j}@@"]
108
+ str["@@tdiary-style-markdown-plugin#{j}@@"] = CGI.escapeHTML(p_str)
109
+ end
110
+ end
111
+ r["@@tdiary-style-markdown-pre_tag#{i}@@"] = str
112
+ end
113
+ code_tag_stashes.each.with_index do |str, i|
114
+ plugin_stashes.each.with_index do |(p_str, p_erb), j|
115
+ if str["@@tdiary-style-markdown-plugin#{j}@@"]
116
+ str["@@tdiary-style-markdown-plugin#{j}@@"] = CGI.escapeHTML(p_str)
117
+ end
118
+ end
119
+ r["@@tdiary-style-markdown-code_tag#{i}@@"] = str
120
+ end
121
+ plugin_stashes.each.with_index do |(str, erb), i|
122
+ if r["@@tdiary-style-markdown-plugin#{i}@@"]
123
+ r["@@tdiary-style-markdown-plugin#{i}@@"] = erb
124
+ end
125
+ end
126
+
127
+ r
128
+ end
129
+
130
+ def get_categories
131
+ return [] unless @subtitle
132
+ cat = /(\\?\[([^\[]+?)\\?\])+/.match(@subtitle).to_a[0]
133
+ return [] unless cat
134
+ cat.scan(/\\?\[(.*?)\\?\]/).collect do |c|
135
+ c[0].split(/,/)
136
+ end.flatten
137
+ end
138
+
139
+ def strip_subtitle
140
+ return nil unless @subtitle
141
+ r = @subtitle.sub(/^((\\?\[[^\[]+?\]\\?)+\s+)?/, '')
142
+ if r.empty?
143
+ nil
144
+ else
145
+ r
146
+ end
147
+ end
148
+ end
149
+
150
+ class MarkdownDiary
151
+ def initialize(date, title, body, modified = Time.now)
152
+ init_diary
153
+ replace( date, title, body )
154
+ @last_modified = modified
155
+ end
156
+
157
+ def style
158
+ 'Markdown'
159
+ end
160
+
161
+ def append(body, author = nil)
162
+ in_code_block = false
163
+ section = nil
164
+ body.each_line do |l|
165
+ case l
166
+ when /^\#[^\#]/
167
+ if in_code_block
168
+ section << l
169
+ else
170
+ @sections << MarkdownSection.new(section, author) if section
171
+ section = l
172
+ end
173
+ when /^```/
174
+ in_code_block = !in_code_block
175
+ section << l
176
+ else
177
+ section = '' unless section
178
+ section << l
179
+ end
180
+ end
181
+ if section
182
+ section << "\n" unless section =~ /\n\n\z/
183
+ @sections << MarkdownSection.new(section, author)
184
+ end
185
+ @last_modified = Time.now
186
+ self
187
+ end
188
+
189
+ def add_section(subtitle, body)
190
+ @sections = MarkdownSection.new("\# #{subtitle}\n\n#{body}")
191
+ @sections.size
192
+ end
193
+ end
194
+
195
+ class HTMLwithPygments < Redcarpet::Render::HTML
196
+ def block_code(code, language)
197
+ Pygments.highlight(code, lexer: language)
198
+ end
199
+ end
200
+ end
201
+ end
202
+
203
+ # Local Variables:
204
+ # mode: ruby
205
+ # indent-tabs-mode: t
206
+ # tab-width: 3
207
+ # ruby-indent-level: 3
208
+ # End:
@@ -0,0 +1 @@
1
+ require "tdiary/style/markdown"
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'tdiary/style/markdown/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "tdiary-style-markdown"
8
+ spec.version = TDiary::Style::Markdown::VERSION
9
+ spec.authors = ["Kenji Okimoto"]
10
+ spec.email = ["okimoto@clear-code.com"]
11
+ spec.description = %q{Markdown Style for tDiary}
12
+ spec.summary = %q{Markdown Style for tDiary}
13
+ spec.homepage = "https://github.com/clear-code/tdiary-style-markdown"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'redcarpet'
22
+ spec.add_dependency 'pygments.rb'
23
+ spec.add_dependency 'twitter-text'
24
+ spec.add_dependency 'gemoji'
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "test-unit"
29
+ end
data/test/run-test.rb ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # Copyright (C) 2013 Kouhei Sutou <kou@clear-code.com>
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
18
+
19
+ $VERBOSE = true
20
+
21
+ top_dir = File.expand_path(File.join(File.dirname(__FILE__), ".."))
22
+ lib_dir = File.join(top_dir, "lib")
23
+ test_dir = File.dirname(__FILE__)
24
+
25
+ require "test-unit"
26
+
27
+ $LOAD_PATH.unshift(lib_dir)
28
+
29
+ exit Test::Unit::AutoRunner.run(true, test_dir)