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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +0 -0
  6. data/.travis.yml +8 -0
  7. data/CONTRIBUTING.md +44 -0
  8. data/Gemfile +13 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +210 -0
  11. data/Rakefile +8 -0
  12. data/bin/qiitam +34 -0
  13. data/lib/display.rb +10 -0
  14. data/lib/display/display_consts.rb +35 -0
  15. data/lib/display/displayer.rb +81 -0
  16. data/lib/file_writer.rb +19 -0
  17. data/lib/models/article.rb +38 -0
  18. data/lib/models/articles.rb +40 -0
  19. data/lib/qiita_json_loader.rb +43 -0
  20. data/lib/qiita_matome/version.rb +4 -0
  21. data/lib/qiita_matome_core.rb +121 -0
  22. data/lib/qiita_matome_dsl.rb +31 -0
  23. data/lib/qiita_matome_dsl_model.rb +37 -0
  24. data/lib/sort.rb +10 -0
  25. data/lib/sort/sort_consts.rb +28 -0
  26. data/lib/sort/sorter.rb +51 -0
  27. data/lib/validators.rb +13 -0
  28. data/lib/validators/article_validator.rb +19 -0
  29. data/lib/validators/articles_validator.rb +16 -0
  30. data/lib/validators/display_columns_validator.rb +41 -0
  31. data/lib/validators/sort_type_validator.rb +19 -0
  32. data/manual_test_docs/.gitkeep +0 -0
  33. data/qiita_matome.gemspec +28 -0
  34. data/samples/matome_title_asc.md +25 -0
  35. data/spec/display/displayer_spec.rb +341 -0
  36. data/spec/file_writer_spec.rb +92 -0
  37. data/spec/models/article_spec.rb +131 -0
  38. data/spec/models/articles_spec.rb +305 -0
  39. data/spec/qiita_matome_core_spec.rb +46 -0
  40. data/spec/sort/sorter_spec.rb +392 -0
  41. data/spec/spec_helper.rb +16 -0
  42. data/spec/validators/article_validator_spec.rb +53 -0
  43. data/spec/validators/articles_validator_spec.rb +54 -0
  44. data/spec/validators/display_columns_validator_spec.rb +58 -0
  45. data/spec/validators/sort_type_validator_spec.rb +54 -0
  46. metadata +202 -0
@@ -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,4 @@
1
+ # QiitaMatome
2
+ module QiitaMatome
3
+ VERSION = '0.0.1'
4
+ 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
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ require 'sort/sorter'
4
+ require 'sort/sort_consts'
5
+
6
+ module QiitaMatome
7
+ # QiitaMatome::Sort
8
+ module Sort
9
+ end
10
+ end
@@ -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
@@ -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
@@ -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