qiita_matome 0.0.1
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +22 -0
- data/.rspec +2 -0
- data/.rubocop.yml +0 -0
- data/.travis.yml +8 -0
- data/CONTRIBUTING.md +44 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +210 -0
- data/Rakefile +8 -0
- data/bin/qiitam +34 -0
- data/lib/display.rb +10 -0
- data/lib/display/display_consts.rb +35 -0
- data/lib/display/displayer.rb +81 -0
- data/lib/file_writer.rb +19 -0
- data/lib/models/article.rb +38 -0
- data/lib/models/articles.rb +40 -0
- data/lib/qiita_json_loader.rb +43 -0
- data/lib/qiita_matome/version.rb +4 -0
- data/lib/qiita_matome_core.rb +121 -0
- data/lib/qiita_matome_dsl.rb +31 -0
- data/lib/qiita_matome_dsl_model.rb +37 -0
- data/lib/sort.rb +10 -0
- data/lib/sort/sort_consts.rb +28 -0
- data/lib/sort/sorter.rb +51 -0
- data/lib/validators.rb +13 -0
- data/lib/validators/article_validator.rb +19 -0
- data/lib/validators/articles_validator.rb +16 -0
- data/lib/validators/display_columns_validator.rb +41 -0
- data/lib/validators/sort_type_validator.rb +19 -0
- data/manual_test_docs/.gitkeep +0 -0
- data/qiita_matome.gemspec +28 -0
- data/samples/matome_title_asc.md +25 -0
- data/spec/display/displayer_spec.rb +341 -0
- data/spec/file_writer_spec.rb +92 -0
- data/spec/models/article_spec.rb +131 -0
- data/spec/models/articles_spec.rb +305 -0
- data/spec/qiita_matome_core_spec.rb +46 -0
- data/spec/sort/sorter_spec.rb +392 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/validators/article_validator_spec.rb +53 -0
- data/spec/validators/articles_validator_spec.rb +54 -0
- data/spec/validators/display_columns_validator_spec.rb +58 -0
- data/spec/validators/sort_type_validator_spec.rb +54 -0
- metadata +202 -0
data/lib/file_writer.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module QiitaMatome
|
4
|
+
# QiitaMatome FileWriter
|
5
|
+
class FileWriter
|
6
|
+
attr_reader :output_file, :contents
|
7
|
+
|
8
|
+
def initialize(output_file, contents)
|
9
|
+
@output_file = output_file
|
10
|
+
@contents = contents
|
11
|
+
end
|
12
|
+
|
13
|
+
def write
|
14
|
+
dir = File.dirname(@output_file)
|
15
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
16
|
+
File.open(@output_file, 'w:UTF-8') { |f|f.print @contents }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
module QiitaMatome
|
4
|
+
# QiitaMatome::Article
|
5
|
+
class Article
|
6
|
+
YMDHMS_DATETIME_FORMAT = '%Y/%m/%d %H:%M:%S'.freeze
|
7
|
+
attr_accessor :user, :title, :uuid, :created_at, :updated_at, :tags, :stock_count # rubocop:disable LineLength
|
8
|
+
|
9
|
+
# rubocop:disable MethodLength
|
10
|
+
def initialize(options = {})
|
11
|
+
@uuid = options['uuid']
|
12
|
+
@user = options['user']
|
13
|
+
@title = options['title']
|
14
|
+
@uuid = options['uuid']
|
15
|
+
c_at = options['created_at']
|
16
|
+
u_at = options['updated_at']
|
17
|
+
@created_at = DateTime.parse(c_at) unless c_at.nil?
|
18
|
+
@updated_at = DateTime.parse(u_at) unless u_at.nil?
|
19
|
+
@tags = options['tags']
|
20
|
+
@stock_count = options['stock_count']
|
21
|
+
yield(self) if block_given?
|
22
|
+
end
|
23
|
+
# rubocop:enable MethodLength
|
24
|
+
|
25
|
+
def created_at_ymdhms
|
26
|
+
@created_at.strftime(YMDHMS_DATETIME_FORMAT)
|
27
|
+
end
|
28
|
+
|
29
|
+
def updated_at_ymdhms
|
30
|
+
@updated_at.strftime(YMDHMS_DATETIME_FORMAT)
|
31
|
+
end
|
32
|
+
|
33
|
+
def title_link
|
34
|
+
url_name = user['url_name']
|
35
|
+
"[#{title.gsub('|', '')}](http://qiita.com/#{url_name}/items/#{uuid})"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'models/article'
|
2
|
+
|
3
|
+
module QiitaMatome
|
4
|
+
# QiitaMatome::Articles
|
5
|
+
class Articles
|
6
|
+
include Enumerable
|
7
|
+
attr_accessor :articles
|
8
|
+
|
9
|
+
def self.exclude_uuid(target_articles, uuids)
|
10
|
+
uuids_list = Array(uuids)
|
11
|
+
target_articles.delete_if { |e|uuids_list.include?(e.uuid) }
|
12
|
+
target_articles
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(articles = [])
|
16
|
+
@articles = articles
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(article)
|
20
|
+
@articles << article
|
21
|
+
end
|
22
|
+
|
23
|
+
def +(other)
|
24
|
+
@articles += other.articles
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
@articles.size
|
30
|
+
end
|
31
|
+
|
32
|
+
def each
|
33
|
+
@articles.each { |article|yield(article) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def filter_by_tag(tag)
|
37
|
+
@articles.select { |e|e.tags.map { |t|t['name'] }.include?(tag) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'openssl'
|
3
|
+
require 'json'
|
4
|
+
require 'models/article'
|
5
|
+
require 'models/articles'
|
6
|
+
|
7
|
+
module QiitaMatome
|
8
|
+
# QiitaMatome::QiitaJsonLoader
|
9
|
+
class QiitaJsonLoader
|
10
|
+
attr_reader :user, :articles
|
11
|
+
QIITA_URL = 'https://qiita.com/api/v1/users/%s/items?page=%s&per_page=%s'
|
12
|
+
PER_PAGE = 25
|
13
|
+
PAGE_LIMIT = 100
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@articles = Articles.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def load(user)
|
20
|
+
@user = user
|
21
|
+
tmp_verbose = $VERBOSE
|
22
|
+
$VERBOSE = nil
|
23
|
+
OpenSSL::SSL.const_set('VERIFY_PEER', OpenSSL::SSL::VERIFY_NONE)
|
24
|
+
$VERBOSE = tmp_verbose
|
25
|
+
(1..PAGE_LIMIT).each do |page|
|
26
|
+
before_size = @articles.size
|
27
|
+
load_page(user, page)
|
28
|
+
break if before_size == @articles.size
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def load_page(user, page)
|
35
|
+
json = open(format(QIITA_URL, user, page, PER_PAGE)).read
|
36
|
+
json_articles = JSON.parser.new(json).parse
|
37
|
+
@articles += json_articles.each_with_object(Articles.new) do |item, memo|
|
38
|
+
memo << Article.new(item)
|
39
|
+
memo
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'display/displayer'
|
3
|
+
require 'file_writer'
|
4
|
+
require 'models/article'
|
5
|
+
require 'models/articles'
|
6
|
+
require 'qiita_json_loader'
|
7
|
+
require 'qiita_matome_dsl'
|
8
|
+
require 'sort/sorter'
|
9
|
+
|
10
|
+
module QiitaMatome
|
11
|
+
# QiitaMatome Core
|
12
|
+
class Core
|
13
|
+
QIITA_MATOME_FILE = 'Qiitamatomefile'
|
14
|
+
|
15
|
+
# rubocop:disable LineLength
|
16
|
+
QIITA_MATOME_TEMPLATE = <<-EOS
|
17
|
+
# encoding: utf-8
|
18
|
+
|
19
|
+
# Set your qiita user name
|
20
|
+
# user is required
|
21
|
+
# user allow only String
|
22
|
+
user "your value"
|
23
|
+
|
24
|
+
# Set your matome target tag name
|
25
|
+
# tag is required
|
26
|
+
# tag allow only String
|
27
|
+
tag "your value"
|
28
|
+
|
29
|
+
# Set your matome title
|
30
|
+
# title is required
|
31
|
+
# title allow only String
|
32
|
+
title "your value"
|
33
|
+
|
34
|
+
# Set your matome file's output path
|
35
|
+
# output_file is required
|
36
|
+
# output_file allow only String
|
37
|
+
# output_file's default value => "matome.md"
|
38
|
+
output_file "matome.md"
|
39
|
+
|
40
|
+
# Set your matome sort type. you can choose created_at_asc/desc, updated_at_asc/desc, title_asc/desc, stock_count_asc/desc
|
41
|
+
# sort_type allow only String
|
42
|
+
# sort_type's default value => "created_at_desc"
|
43
|
+
sort_type "created_at_desc"
|
44
|
+
|
45
|
+
# Set your matome display columns. you can choose :title, :created_at, :updated_at, :stock_count and :no
|
46
|
+
# display_columns allow only Array
|
47
|
+
# display_columns's default value => [:no, :title, :created_at, :stock_count]
|
48
|
+
display_columns [:no, :title, :created_at, :stock_count]
|
49
|
+
|
50
|
+
# Set your matome exclude files
|
51
|
+
# excludes allow only Array[String, String ...]
|
52
|
+
# String is uuid. For example, 'edbfecb6a6789dd54f47'
|
53
|
+
# excludes's default value => []
|
54
|
+
excludes []
|
55
|
+
EOS
|
56
|
+
# rubocop:enable LineLength
|
57
|
+
|
58
|
+
# Generate Qiitamatomefile to current directory.
|
59
|
+
def init
|
60
|
+
File.open(QIITA_MATOME_FILE, 'w') { |f|f.puts QIITA_MATOME_TEMPLATE }
|
61
|
+
end
|
62
|
+
|
63
|
+
# Generate QiitaMatome markdown file.
|
64
|
+
def matome
|
65
|
+
dsl = read_dsl
|
66
|
+
articles = read_articles(dsl)
|
67
|
+
excluded_articles = read_excluded_articles(dsl, articles)
|
68
|
+
sorted_articles = read_sorted_articles(dsl, excluded_articles)
|
69
|
+
title = dsl.qiita_matome.title
|
70
|
+
display_columns = dsl.qiita_matome.display_columns
|
71
|
+
markdown = read_markdown(sorted_articles, title, display_columns)
|
72
|
+
output_file = dsl.qiita_matome.output_file
|
73
|
+
fw = QiitaMatome::FileWriter.new(output_file, markdown)
|
74
|
+
fw.write
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def read_dsl
|
80
|
+
src = File.open(QIITA_MATOME_FILE) { |f|f.read }
|
81
|
+
dsl = QiitaMatome::Dsl.new
|
82
|
+
dsl.instance_eval src
|
83
|
+
dsl
|
84
|
+
end
|
85
|
+
|
86
|
+
def read_articles(dsl)
|
87
|
+
user = dsl.qiita_matome.user
|
88
|
+
qjl = QiitaJsonLoader.new
|
89
|
+
qjl.load(user)
|
90
|
+
qjl.articles
|
91
|
+
end
|
92
|
+
|
93
|
+
def read_excluded_articles(dsl, articles)
|
94
|
+
tag = dsl.qiita_matome.tag
|
95
|
+
filterd_articles = articles.filter_by_tag(tag)
|
96
|
+
uuids = dsl.qiita_matome.excludes
|
97
|
+
Articles.exclude_uuid(filterd_articles, uuids)
|
98
|
+
end
|
99
|
+
|
100
|
+
def read_sorted_articles(dsl, articles)
|
101
|
+
sort_type = dsl.qiita_matome.sort_type
|
102
|
+
sorter = Sort::Sorter.new(articles, sort_type)
|
103
|
+
sorter.sort
|
104
|
+
end
|
105
|
+
|
106
|
+
def read_markdown(articles, title, display_columns)
|
107
|
+
dd = Display::Displayer.new(title, articles, display_columns)
|
108
|
+
display_title = dd.display_title
|
109
|
+
matome_updated = dd.matome_updated
|
110
|
+
table_header = dd.table_header
|
111
|
+
display_articles = dd.display_articles
|
112
|
+
<<-EOS
|
113
|
+
#{display_title}
|
114
|
+
|
115
|
+
#{matome_updated}
|
116
|
+
|
117
|
+
#{table_header}#{display_articles}
|
118
|
+
EOS
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'qiita_matome_dsl_model'
|
3
|
+
|
4
|
+
module QiitaMatome
|
5
|
+
# Dsl
|
6
|
+
class Dsl
|
7
|
+
attr_accessor :qiita_matome
|
8
|
+
|
9
|
+
# String Define
|
10
|
+
[:user, :tag, :title, :output_file, :sort_type].each do |f|
|
11
|
+
define_method f do |value|
|
12
|
+
@qiita_matome.send("#{f}=", value)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Array/Hash/Boolean Define
|
17
|
+
[:display_columns, :excludes].each do |f|
|
18
|
+
define_method f do |value|
|
19
|
+
@qiita_matome.send("#{f}=", value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@qiita_matome = QiitaMatome::DslModel.new
|
25
|
+
@qiita_matome.output_file = 'matome.md'
|
26
|
+
@qiita_matome.sort_type = 'created_at_desc'
|
27
|
+
@qiita_matome.display_columns = [:no, :title, :create_date, :stocked]
|
28
|
+
@qiita_matome.excludes = []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'active_model'
|
3
|
+
|
4
|
+
module QiitaMatome
|
5
|
+
# DslModel
|
6
|
+
class DslModel
|
7
|
+
include ActiveModel::Model
|
8
|
+
|
9
|
+
# Set your qiita user name
|
10
|
+
attr_accessor :user
|
11
|
+
validates :user, presence: true
|
12
|
+
|
13
|
+
# Set your matome target tag name
|
14
|
+
attr_accessor :tag
|
15
|
+
validates :tag, presence: true
|
16
|
+
|
17
|
+
# Set your matome title
|
18
|
+
attr_accessor :title
|
19
|
+
validates :title, presence: true
|
20
|
+
|
21
|
+
# Set your matome file's output path
|
22
|
+
attr_accessor :output_file
|
23
|
+
validates :output_file, presence: true
|
24
|
+
|
25
|
+
# Set your matome sort type.
|
26
|
+
# you can choose created_at_asc/desc, updated_at_asc/desc,
|
27
|
+
# title_asc/desc, stock_count_asc/desc
|
28
|
+
attr_accessor :sort_type
|
29
|
+
|
30
|
+
# Set your matome display columns.
|
31
|
+
# you can choose :title, :create_date, :update_date, :stocked and :no
|
32
|
+
attr_accessor :display_columns
|
33
|
+
|
34
|
+
# Set your matome exclude files
|
35
|
+
attr_accessor :excludes
|
36
|
+
end
|
37
|
+
end
|
data/lib/sort.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module QiitaMatome
|
4
|
+
# QiitaMatome::Sort
|
5
|
+
module Sort
|
6
|
+
# QiitaMatome::Sort::Consts
|
7
|
+
module Consts
|
8
|
+
CREATED_AT_ASC = 'created_at_asc'.freeze
|
9
|
+
CREATED_AT_DESC = 'created_at_desc'.freeze
|
10
|
+
UPDATED_AT_ASC = 'updated_at_asc'.freeze
|
11
|
+
UPDATED_AT_DESC = 'updated_at_desc'.freeze
|
12
|
+
TITLE_ASC = 'title_asc'.freeze
|
13
|
+
TITLE_DESC = 'title_desc'.freeze
|
14
|
+
STOCK_COUNT_ASC = 'stock_count_asc'.freeze
|
15
|
+
STOCK_COUNT_DESC = 'stock_count_desc'.freeze
|
16
|
+
ALL_TYPES = [
|
17
|
+
CREATED_AT_ASC,
|
18
|
+
CREATED_AT_DESC,
|
19
|
+
UPDATED_AT_ASC,
|
20
|
+
UPDATED_AT_DESC,
|
21
|
+
TITLE_ASC,
|
22
|
+
TITLE_DESC,
|
23
|
+
STOCK_COUNT_ASC,
|
24
|
+
STOCK_COUNT_DESC
|
25
|
+
]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/sort/sorter.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'sort/sort_consts'
|
3
|
+
require 'validators/article_validator'
|
4
|
+
require 'validators/articles_validator'
|
5
|
+
require 'validators/sort_type_validator'
|
6
|
+
|
7
|
+
module QiitaMatome
|
8
|
+
# QiitaMatome::Sort
|
9
|
+
module Sort
|
10
|
+
# QiitaMatome::Sort::Sorter
|
11
|
+
class Sorter
|
12
|
+
attr_reader :articles, :sort_type
|
13
|
+
|
14
|
+
# rubocop:disable LineLength
|
15
|
+
SORT_PATTERNS = {
|
16
|
+
Consts::CREATED_AT_ASC => { send_method: :sort_asc, sort_key: :created_at },
|
17
|
+
Consts::CREATED_AT_DESC => { send_method: :sort_desc, sort_key: :created_at },
|
18
|
+
Consts::UPDATED_AT_ASC => { send_method: :sort_asc, sort_key: :updated_at },
|
19
|
+
Consts::UPDATED_AT_DESC => { send_method: :sort_desc, sort_key: :updated_at },
|
20
|
+
Consts::TITLE_ASC => { send_method: :sort_asc, sort_key: :title },
|
21
|
+
Consts::TITLE_DESC => { send_method: :sort_desc, sort_key: :title },
|
22
|
+
Consts::STOCK_COUNT_ASC => { send_method: :sort_asc, sort_key: :stock_count },
|
23
|
+
Consts::STOCK_COUNT_DESC => { send_method: :sort_desc, sort_key: :stock_count }
|
24
|
+
}
|
25
|
+
# rubocop:enable LineLength
|
26
|
+
|
27
|
+
def initialize(articles, sort_type = Consts::UPDATED_AT_DESC)
|
28
|
+
Validators::ArticlesValidator.validate(articles)
|
29
|
+
Validators::ArticleValidator.validate(articles)
|
30
|
+
Validators::SortTypeValidator.validate(sort_type)
|
31
|
+
@articles = articles
|
32
|
+
@sort_type = sort_type
|
33
|
+
end
|
34
|
+
|
35
|
+
def sort
|
36
|
+
sort_pattern = SORT_PATTERNS[@sort_type]
|
37
|
+
send(sort_pattern[:send_method], sort_pattern[:sort_key])
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def sort_asc(asc_key)
|
43
|
+
@articles.sort_by! { |e|e.send(asc_key) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def sort_desc(desc_key)
|
47
|
+
@articles = @articles.sort_by { |e|e.send(desc_key) }.reverse
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/validators.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'validators/article_validator'
|
4
|
+
require 'validators/articles_validator'
|
5
|
+
require 'validators/display_columns_validator'
|
6
|
+
require 'validators/sort_type_validator'
|
7
|
+
require 'validators/sort_type_validator'
|
8
|
+
|
9
|
+
module QiitaMatome
|
10
|
+
# QiitaMatome::Validators
|
11
|
+
module Validators
|
12
|
+
end
|
13
|
+
end
|