tocer 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ced1fb93f4c52c60a2ea5269d5dbb26f6987fb3a
4
- data.tar.gz: 9526ee10285dead69f802fbd995f48dd8c22061b
3
+ metadata.gz: 2f12d5a3b405216b970f03b881e0a36c00e0091f
4
+ data.tar.gz: 898e0ba35499767b75fe50e88f15e62f6a95bb6f
5
5
  SHA512:
6
- metadata.gz: 21eb3f82c3020bc95a939f01d02f63752a5b060750606e68398f9e9cb8419f603998391dab13b71474df195771686f24742fc86c3c88737892064a0e2dbdafcf
7
- data.tar.gz: b9bcc33e6ce0dbed48268305c7ea499ee765d4d614571f2497340d8264f63ce552643d35deb59c29c78a1e3edefb39cb37b0f980500a2b42790c81940f2b9d4d
6
+ metadata.gz: 6da1ab64f2fba3c688711ddc88e6c732e6c19e2b29f4da278f8c4d9cff7fbb6d4f028a6969b042eed9539cce04e9ab1de2407d98d71537b3c239c4d706f6219f
7
+ data.tar.gz: 615fa828848a718049deec38252626d94d9a4d279a618109afa2c743580e5441f9c694d38077122ceedc8a6e4aa5de455b7deacfb55da240a1b841eb64db120a
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -9,14 +9,16 @@
9
9
 
10
10
  Tocer (a.k.a. Table of Contenter) is command line interface for generating table of contents for Markdown files.
11
11
 
12
- <!-- START doctoc generated TOC please keep comment here to allow auto update -->
13
- <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
12
+ <!-- Tocer[start]: Auto-generated, don't remove. -->
13
+
14
14
  # Table of Contents
15
15
 
16
16
  - [Features](#features)
17
17
  - [Requirements](#requirements)
18
18
  - [Setup](#setup)
19
19
  - [Usage](#usage)
20
+ - [Command Line Interface (CLI)](#command-line-interface-cli)
21
+ - [Customization](#customization)
20
22
  - [Tests](#tests)
21
23
  - [Versioning](#versioning)
22
24
  - [Code of Conduct](#code-of-conduct)
@@ -25,13 +27,13 @@ Tocer (a.k.a. Table of Contenter) is command line interface for generating table
25
27
  - [History](#history)
26
28
  - [Credits](#credits)
27
29
 
28
- <!-- END doctoc generated TOC please keep comment here to allow auto update -->
30
+ <!-- Tocer[finish]: Auto-generated, don't remove. -->
29
31
 
30
32
  # Features
31
33
 
32
34
  - Supports Markdown ATX-style headers. Example: `# Header`.
33
35
  - Does not support header suffixes. Example: `# Header #`.
34
- - Does not support header previxes without spaces. Example: `#Header`.
36
+ - Does not support header prefixes without spaces. Example: `#Header`.
35
37
  - Prepends table of contents to Markdown documents that don't have table of contents.
36
38
  - Replaces/updates Markdown documents that have existing table of contents.
37
39
 
@@ -56,6 +58,8 @@ For an insecure install, type the following (not recommended):
56
58
 
57
59
  # Usage
58
60
 
61
+ ## Command Line Interface (CLI)
62
+
59
63
  From the command line, type: `tocer help`
60
64
 
61
65
  tocer -e, [--edit] # Edit Tocer settings in default editor.
@@ -66,8 +70,8 @@ From the command line, type: `tocer help`
66
70
  To add Tocer support, add the following at the correct position within your Markdown files:
67
71
 
68
72
  ```
69
- <!-- Tocer[start]: Auto-generated, don't remove. -->
70
- <!-- Tocer[finish]: Auto-generated, don't remove. -->
73
+ <!-- Tocer[start] -->
74
+ <!-- Tocer[finish] -->
71
75
  ```
72
76
 
73
77
  Alternatively, you can run `tocer -g <file_path>` on a file that does not have Tocer support and it will prepend the above
@@ -77,6 +81,25 @@ In the case that Tocer has already auto-generated a table of contents for a Mark
77
81
  contents has become stale, or placement of the table of contents has changed you can re-run Tocer on that file to auto-
78
82
  update it with new table of contents.
79
83
 
84
+ ## Customization
85
+
86
+ If desired, this gem supports global customization via the `~/.tocerrc` file. Order of precedence is determined in the
87
+ following order (with the last one taking top priority):
88
+
89
+ 0. Global `~/.tocerrc`.
90
+ 0. CLI option. Example: `tocer --generate README.md --label "Custom Label"`
91
+
92
+ Any setting provided to the CLI during runtime would trump the global setting. The global setting is the weakest of all
93
+ but great for situations where custom settings should be applied to *all* projects.
94
+
95
+ The `~/.tocerrc` uses the following default settings:
96
+
97
+ :label: "# Table of Contents"
98
+
99
+ Each `~/.tocerrc` setting can be configured as follows:
100
+
101
+ - `label`: The header label for the table of contents. Default: "# Table of Contents".
102
+
80
103
  # Tests
81
104
 
82
105
  To test, run:
data/lib/tocer.rb CHANGED
@@ -1,5 +1,8 @@
1
+ require "tocer/elements/comment_block"
2
+ require "tocer/parsers/header"
3
+ require "tocer/transformers/link"
4
+ require "tocer/transformers/text"
1
5
  require "tocer/builder"
2
- require "tocer/commenter"
6
+ require "tocer/configuration"
3
7
  require "tocer/identity"
4
- require "tocer/transformer"
5
8
  require "tocer/writer"
data/lib/tocer/builder.rb CHANGED
@@ -1,32 +1,52 @@
1
1
  module Tocer
2
- # Builds table of contents for a document in Markdown.
2
+ # Builds a table of contents for a Markdown document.
3
3
  class Builder
4
- def initialize lines, label: "# Table of Contents", transformer: Transformer, commenter: Commenter
4
+ def initialize lines, label: "# Table of Contents", comment_block: Elements::CommentBlock
5
5
  @lines = lines
6
6
  @label = label
7
- @transformer = transformer
8
- @commenter = commenter.new
7
+ @comment_block = comment_block.new
8
+ @url_count = Hash.new { |hash, key| hash[key] = 0 }
9
9
  end
10
10
 
11
11
  def headers
12
- lines.select { |line| line.start_with? "#" }
12
+ lines.select { |line| line.start_with? Parsers::Header.punctuation }
13
13
  end
14
14
 
15
15
  def build
16
16
  return "" if headers.empty?
17
17
 
18
- content = "#{commenter.start}\n\n"
18
+ content = "#{comment_block.start}\n\n"
19
19
  content << "#{label}\n\n"
20
20
  content << headers_as_links.join("\n")
21
- content << "\n\n#{commenter.finish}\n\n"
21
+ content << "\n\n#{comment_block.finish}\n\n"
22
22
  end
23
23
 
24
24
  private
25
25
 
26
- attr_reader :lines, :label, :transformer, :commenter
26
+ attr_reader :lines, :label, :comment_block, :url_count
27
+
28
+ def acquire_transfomer header
29
+ case
30
+ when header =~ /\[.+\]\(.+\)/
31
+ Transformers::Link.new header
32
+ else
33
+ Transformers::Text.new header
34
+ end
35
+ end
36
+
37
+ def url_suffix url
38
+ url_count[url].zero? ? "" : url_count[url]
39
+ end
40
+
41
+ def transform header
42
+ transformer = acquire_transfomer header
43
+ link = transformer.transform url_suffix: url_suffix(transformer.url)
44
+ url_count[transformer.url] += 1
45
+ link
46
+ end
27
47
 
28
48
  def headers_as_links
29
- headers.map { |header| transformer.new(header).transform }
49
+ headers.map { |header| transform header }
30
50
  end
31
51
  end
32
52
  end
data/lib/tocer/cli.rb CHANGED
@@ -13,13 +13,15 @@ module Tocer
13
13
 
14
14
  def initialize args = [], options = {}, config = {}
15
15
  super args, options, config
16
+ @configuration = Configuration.new
16
17
  end
17
18
 
18
19
  desc "-g, [--generate=GENERATE]", "Generate table of contents."
19
20
  map %w(-g --generate) => :generate
21
+ method_option :label, aliases: "-l", desc: "Custom label", type: :string, default: "# Table of Contents"
20
22
  def generate file_path
21
- writer = Writer.new file_path
22
- writer.write
23
+ update_configuration! options
24
+ Writer.new(file_path, label: configuration.label).write
23
25
  say "Generated table of contents: #{file_path}."
24
26
  end
25
27
 
@@ -42,5 +44,14 @@ module Tocer
42
44
  def help task = nil
43
45
  say && super
44
46
  end
47
+
48
+ private
49
+
50
+ attr_reader :configuration
51
+
52
+ def update_configuration! options
53
+ return if options[:label] == "# Table of Contents"
54
+ configuration.label = options[:label]
55
+ end
45
56
  end
46
57
  end
@@ -0,0 +1,26 @@
1
+ module Tocer
2
+ # Default configuration for gem with support for custom settings.
3
+ class Configuration
4
+ attr_reader :file_path
5
+ attr_writer :label
6
+
7
+ def initialize file_path: File.join(ENV["HOME"], Identity.file_name)
8
+ @file_path = file_path
9
+ @settings = load_settings
10
+ end
11
+
12
+ def label
13
+ @label ||= settings.fetch(:label, "# Table of Contents")
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :settings
19
+
20
+ def load_settings
21
+ return {} unless File.exist?(file_path)
22
+ yaml = YAML.load_file file_path
23
+ yaml.is_a?(Hash) ? yaml : {}
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ module Tocer
2
+ module Elements
3
+ # Represents a table of contents start and finish comment block.
4
+ class CommentBlock
5
+ def initialize start_id: "Tocer[start]", finish_id: "Tocer[finish]", message: "Auto-generated, don't remove."
6
+ @start_id = start_id
7
+ @finish_id = finish_id
8
+ @message = message
9
+ end
10
+
11
+ def start
12
+ comment start_id, message
13
+ end
14
+
15
+ def start_index collection
16
+ index collection, start_id
17
+ end
18
+
19
+ def finish
20
+ comment finish_id, message
21
+ end
22
+
23
+ def finish_index collection
24
+ index collection, finish_id
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :start_id, :finish_id, :message
30
+
31
+ def comment id, message
32
+ "<!-- #{id}: #{message} -->"
33
+ end
34
+
35
+ def index collection, id
36
+ collection.index { |line| line =~ /\<\!\-\-.*#{Regexp.escape id}.*\-\-\>/ }
37
+ end
38
+ end
39
+ end
40
+ end
@@ -10,7 +10,7 @@ module Tocer
10
10
  end
11
11
 
12
12
  def self.version
13
- "0.1.0"
13
+ "1.0.0"
14
14
  end
15
15
 
16
16
  def self.version_label
@@ -0,0 +1,26 @@
1
+ module Tocer
2
+ module Parsers
3
+ # Represents a Markdown header.
4
+ class Header
5
+ def self.punctuation
6
+ "#"
7
+ end
8
+
9
+ def initialize markdown
10
+ @markdown = markdown
11
+ end
12
+
13
+ def prefix
14
+ String markdown[/#{self.class.punctuation}{1,}/]
15
+ end
16
+
17
+ def content
18
+ markdown[prefix.length + 1, markdown.length].strip
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :markdown
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ require "refinements/array_extensions"
2
+
3
+ module Tocer
4
+ module Transformers
5
+ # Transforms a Markdown header (embedded link) into a table of contents link.
6
+ class Link
7
+ using Refinements::ArrayExtensions
8
+
9
+ def initialize text, header: Parsers::Header
10
+ @header = header.new text
11
+ end
12
+
13
+ def label
14
+ header.content.gsub(embedded_link, embedded_link_label)
15
+ end
16
+
17
+ def url
18
+ label.downcase.gsub(/\s/, "-").gsub(/[^\w\-]+/, "")
19
+ end
20
+
21
+ def transform url_suffix: ""
22
+ modified_url = [url, url_suffix.to_s].compress.join "-"
23
+ "#{indented_bullet}[#{label}](##{modified_url})"
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :header
29
+
30
+ def embedded_link_label
31
+ header.content[/\[(.*)\]/, 1]
32
+ end
33
+
34
+ def embedded_link_url
35
+ header.content[/\((.*)\)/, 1]
36
+ end
37
+
38
+ def embedded_link
39
+ "[#{embedded_link_label}](#{embedded_link_url})"
40
+ end
41
+
42
+ def prefix_to_spaces
43
+ Array.new(header.prefix.length, " ").join
44
+ end
45
+
46
+ def indented_bullet
47
+ prefix_to_spaces.gsub(/\s{2}$/, "- ")
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,39 @@
1
+ require "refinements/array_extensions"
2
+
3
+ module Tocer
4
+ module Transformers
5
+ # Transforms a Markdown header (plain text) into a table of contents link.
6
+ class Text
7
+ using Refinements::ArrayExtensions
8
+
9
+ def initialize text, header: Parsers::Header
10
+ @header = header.new text
11
+ end
12
+
13
+ def label
14
+ header.content
15
+ end
16
+
17
+ def url
18
+ label.downcase.gsub(/\s/, "-").gsub(/[^\w\-]+/, "")
19
+ end
20
+
21
+ def transform url_suffix: ""
22
+ modified_url = [url, url_suffix.to_s].compress.join "-"
23
+ "#{indented_bullet}[#{label}](##{modified_url})"
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :header
29
+
30
+ def prefix_to_spaces
31
+ Array.new(header.prefix.length, " ").join
32
+ end
33
+
34
+ def indented_bullet
35
+ prefix_to_spaces.gsub(/\s{2}$/, "- ")
36
+ end
37
+ end
38
+ end
39
+ end
data/lib/tocer/writer.rb CHANGED
@@ -1,11 +1,12 @@
1
1
  module Tocer
2
2
  # Writes table of contents to a Markdown document.
3
3
  class Writer
4
- def initialize file_path, builder: Builder, commenter: Commenter
4
+ def initialize file_path, label: "# Table of Contents", builder: Builder, comment_block: Elements::CommentBlock
5
5
  @file_path = file_path
6
6
  @file_lines = File.open(file_path).to_a
7
+ @label = label
7
8
  @builder = builder
8
- setup_indexes commenter.new, @file_lines
9
+ setup_indexes comment_block.new, @file_lines
9
10
  end
10
11
 
11
12
  def write
@@ -15,15 +16,15 @@ module Tocer
15
16
 
16
17
  private
17
18
 
18
- attr_reader :file_path, :file_lines, :start_index, :finish_index, :builder, :commenter
19
+ attr_reader :file_path, :file_lines, :label, :start_index, :finish_index, :builder, :comment_block
19
20
 
20
- def setup_indexes commenter, lines
21
- @start_index = commenter.start_index lines
22
- @finish_index = commenter.finish_index lines
21
+ def setup_indexes comment_block, lines
22
+ @start_index = comment_block.start_index lines
23
+ @finish_index = comment_block.finish_index lines
23
24
  end
24
25
 
25
26
  def content lines
26
- builder.new(lines).build
27
+ builder.new(lines, label: label).build
27
28
  end
28
29
 
29
30
  def remove_toc lines
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tocer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brooke Kuhlmann
@@ -30,36 +30,50 @@ cert_chain:
30
30
  aSif+qBc6oHD7EQWPF5cZkzkIURuwNwPBngZGxIKaMAgRhjGFXzUMAaq++r59cS9
31
31
  xTfQ4k6fglKEgpnLAXiKdo2c8Ym+X4rIKFfedQ==
32
32
  -----END CERTIFICATE-----
33
- date: 2015-11-15 00:00:00.000000000 Z
33
+ date: 2015-11-21 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: thor
37
37
  requirement: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: '0'
41
+ version: '0.19'
42
42
  type: :runtime
43
43
  prerelease: false
44
44
  version_requirements: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: '0.19'
49
49
  - !ruby/object:Gem::Dependency
50
50
  name: thor_plus
51
51
  requirement: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ">="
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: '2.1'
56
56
  type: :runtime
57
57
  prerelease: false
58
58
  version_requirements: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - ">="
60
+ - - "~>"
61
61
  - !ruby/object:Gem::Version
62
- version: '0'
62
+ version: '2.1'
63
+ - !ruby/object:Gem::Dependency
64
+ name: refinements
65
+ requirement: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '1.0'
63
77
  - !ruby/object:Gem::Dependency
64
78
  name: rake
65
79
  requirement: !ruby/object:Gem::Requirement
@@ -301,13 +315,16 @@ files:
301
315
  - lib/tocer.rb
302
316
  - lib/tocer/builder.rb
303
317
  - lib/tocer/cli.rb
304
- - lib/tocer/commenter.rb
318
+ - lib/tocer/configuration.rb
319
+ - lib/tocer/elements/comment_block.rb
305
320
  - lib/tocer/identity.rb
321
+ - lib/tocer/parsers/header.rb
306
322
  - lib/tocer/tasks/rspec.rake
307
323
  - lib/tocer/tasks/rubocop.rake
308
- - lib/tocer/transformer.rb
324
+ - lib/tocer/transformers/link.rb
325
+ - lib/tocer/transformers/text.rb
309
326
  - lib/tocer/writer.rb
310
- homepage: https://www.alchemists.io
327
+ homepage: https://github.com/bkuhlmann/tocer
311
328
  licenses:
312
329
  - MIT
313
330
  metadata: {}
metadata.gz.sig CHANGED
Binary file
@@ -1,38 +0,0 @@
1
- module Tocer
2
- # Represents table of contents start and finish comments.
3
- class Commenter
4
- def initialize start_id: "Tocer[start]", finish_id: "Tocer[finish]", message: "Auto-generated, don't remove."
5
- @start_id = start_id
6
- @finish_id = finish_id
7
- @message = message
8
- end
9
-
10
- def start
11
- comment start_id, message
12
- end
13
-
14
- def start_index collection
15
- index collection, start
16
- end
17
-
18
- def finish
19
- comment finish_id, message
20
- end
21
-
22
- def finish_index collection
23
- index collection, finish
24
- end
25
-
26
- private
27
-
28
- attr_reader :start_id, :finish_id, :message
29
-
30
- def comment id, message
31
- "<!-- #{id}: #{message} -->"
32
- end
33
-
34
- def index collection, text
35
- collection.index { |line| line =~ /#{Regexp.escape text}/ }
36
- end
37
- end
38
- end
@@ -1,38 +0,0 @@
1
- module Tocer
2
- # Transforms Markdown headers into anchored links.
3
- class Transformer
4
- def initialize text
5
- @text = text
6
- end
7
-
8
- def pounds
9
- String text[/\#{1,}/]
10
- end
11
-
12
- def label
13
- return "" if text.empty?
14
- text[pounds.length + 1, text.length].strip
15
- end
16
-
17
- def bullet
18
- return "" if pounds.empty?
19
- pounds_to_spaces(pounds).gsub(/\s{2}$/, "- ")
20
- end
21
-
22
- def url
23
- label.downcase.gsub(/\s/, "-").gsub(/[^\w\-\+\&]+/, "")
24
- end
25
-
26
- def transform
27
- "#{bullet}[#{label}](##{url})"
28
- end
29
-
30
- private
31
-
32
- attr_reader :text
33
-
34
- def pounds_to_spaces pounds
35
- Array.new(pounds.length, " ").join
36
- end
37
- end
38
- end