rb_markdown 0.1.1 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6bc421754398dc85316b4b54b251aa80e8ac8a52
4
- data.tar.gz: df0fc841b625ea9118851619879464cfedaa42d6
2
+ SHA256:
3
+ metadata.gz: 17dbdf585f1866132db4a59586f1a718f533282c2abe3112feda769d53797d9e
4
+ data.tar.gz: b54373ccbb44e35b8d5daa3ba3e2f10d52082b49c9088998374898dab68d4810
5
5
  SHA512:
6
- metadata.gz: 6989ce33cf908faba360ee90ec47f2cb5643b8d268126b3e5d463542da833a8f329b2d4ad68e6e2cb15ebbb28d021c2f1fccb943cc3f1e651523acf35dfa327a
7
- data.tar.gz: 140cef551bb837176bb405d6effdcee6fc7825f4cc1cce02cfc91ed9edb94cb5e602fa6b3c60092c09411a51e9d3dfa191f33ab41c33cf2ae3f9080043936a92
6
+ metadata.gz: dc1ccf31f89b17cb52b357e701c9fed65271d672aeb3812df83e85553af981e4e87f11a286fcbbd2ebf84309076ce9663543a257626a40ae54df607adfd0f73a
7
+ data.tar.gz: d673b082a8133b9dfbf691a6b272dce752855d9c230953c79f2e12b1b5b377a51ba6a24c5b8de9d974a572420ab8e9d626afc68c02be56a979ab4026f64daae3
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Markdown
4
+ module AbstractLineTag
5
+ def match?(line)
6
+ line.match?(prefix_pattern)
7
+ end
8
+
9
+ def process(line)
10
+ content = line.sub(prefix_pattern, "")
11
+ convert(content)
12
+ end
13
+
14
+ protected
15
+
16
+ # @return [Regexp]
17
+ def prefix_pattern
18
+ raise NotImplementedError
19
+ end
20
+
21
+ # @param string [String]
22
+ # @return [String]
23
+ def convert(string)
24
+ raise NotImplementedError
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Markdown
4
+ class BlockSplitter
5
+ Segment = Struct.new(:type, :content, :language)
6
+
7
+ def split(string)
8
+ segments = []
9
+ current_lines = []
10
+ in_code_block = false
11
+ language = nil
12
+
13
+ string.each_line do |line|
14
+ line = line.chomp
15
+
16
+ if in_code_block
17
+ if line.match?(/^```\s*$/)
18
+ segments << Segment.new(:code, current_lines.join("\n"), language)
19
+ current_lines = []
20
+ in_code_block = false
21
+ language = nil
22
+ else
23
+ current_lines << line
24
+ end
25
+ elsif (match = line.match(/^```(\w*)\s*$/))
26
+ segments << Segment.new(:text, current_lines.join("\n")) unless current_lines.empty?
27
+ current_lines = []
28
+ in_code_block = true
29
+ language = match[1].empty? ? nil : match[1]
30
+ else
31
+ current_lines << line
32
+ end
33
+ end
34
+
35
+ unless current_lines.empty?
36
+ segments << Segment.new(in_code_block ? :code : :text, current_lines.join("\n"), language)
37
+ end
38
+
39
+ segments
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rouge"
4
+
5
+ module Markdown
6
+ class CodeBlockRenderer
7
+ def render(content, language)
8
+ lexer = Rouge::Lexer.find(language) if language
9
+ lexer ||= Rouge::Lexers::PlainText.new
10
+
11
+ formatter = Rouge::Formatters::Terminal256.new(Rouge::Themes::Monokai.new)
12
+ formatter.format(lexer.lex(content))
13
+ end
14
+ end
15
+ end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "./bold_tag"
4
- require_relative "./code_tag"
5
- require_relative "./italic_tag"
3
+ require_relative "./block_splitter"
4
+ require_relative "./code_block_renderer"
5
+ require_relative "./inline_processor"
6
+ require_relative "./line_processor"
6
7
 
7
8
  module Markdown
8
9
  class Engine
@@ -11,9 +12,17 @@ module Markdown
11
12
  end
12
13
 
13
14
  def to_ansi
14
- # The tags are ordered by priority.
15
- # For example: `Bold` should run before `Italic`.
16
- CodeTag.new(ItalicTag.new(BoldTag.new(@string))).to_ansi
15
+ line_processor = LineProcessor.new(InlineProcessor.new)
16
+ code_renderer = CodeBlockRenderer.new
17
+
18
+ BlockSplitter.new.split(@string).map do |segment|
19
+ case segment.type
20
+ when :text
21
+ line_processor.process(segment.content)
22
+ when :code
23
+ code_renderer.render(segment.content, segment.language)
24
+ end
25
+ end.join("\n")
17
26
  end
18
27
  end
19
28
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./abstract_line_tag"
4
+
5
+ module Markdown
6
+ class HeadingOneTag
7
+ include AbstractLineTag
8
+
9
+ protected
10
+
11
+ def prefix_pattern
12
+ /^#\s+/
13
+ end
14
+
15
+ def convert(string)
16
+ string.bold.underline
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./abstract_line_tag"
4
+
5
+ module Markdown
6
+ class HeadingThreeTag
7
+ include AbstractLineTag
8
+
9
+ protected
10
+
11
+ def prefix_pattern
12
+ /^###\s+/
13
+ end
14
+
15
+ def convert(string)
16
+ string.bold.italic
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./abstract_line_tag"
4
+
5
+ module Markdown
6
+ class HeadingTwoTag
7
+ include AbstractLineTag
8
+
9
+ protected
10
+
11
+ def prefix_pattern
12
+ /^##\s+/
13
+ end
14
+
15
+ def convert(string)
16
+ string.bold
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./bold_tag"
4
+ require_relative "./code_tag"
5
+ require_relative "./italic_tag"
6
+
7
+ module Markdown
8
+ class InlineProcessor
9
+ def process(string)
10
+ CodeTag.new(ItalicTag.new(BoldTag.new(string))).to_ansi
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./heading_three_tag"
4
+ require_relative "./heading_two_tag"
5
+ require_relative "./heading_one_tag"
6
+ require_relative "./unordered_list_tag"
7
+ require_relative "./ordered_list_tag"
8
+
9
+ module Markdown
10
+ class LineProcessor
11
+ def initialize(inline_processor)
12
+ @inline_processor = inline_processor
13
+ @line_tags = [
14
+ HeadingThreeTag.new,
15
+ HeadingTwoTag.new,
16
+ HeadingOneTag.new,
17
+ UnorderedListTag.new,
18
+ OrderedListTag.new,
19
+ ]
20
+ end
21
+
22
+ def process(string)
23
+ string.each_line(chomp: true).map do |line|
24
+ tag = @line_tags.find { |t| t.match?(line) }
25
+
26
+ if tag
27
+ @inline_processor.process(tag.process(line))
28
+ else
29
+ @inline_processor.process(line)
30
+ end
31
+ end.join("\n")
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./abstract_line_tag"
4
+
5
+ module Markdown
6
+ class OrderedListTag
7
+ include AbstractLineTag
8
+
9
+ protected
10
+
11
+ def prefix_pattern
12
+ /^(\d+)\.\s+/
13
+ end
14
+
15
+ def convert(string)
16
+ string
17
+ end
18
+
19
+ public
20
+
21
+ def process(line)
22
+ match = line.match(prefix_pattern)
23
+ content = line.sub(prefix_pattern, "")
24
+ " #{match[1]}. #{convert(content)}"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "./abstract_line_tag"
4
+
5
+ module Markdown
6
+ class UnorderedListTag
7
+ include AbstractLineTag
8
+
9
+ protected
10
+
11
+ def prefix_pattern
12
+ /^[*\-]\s+/
13
+ end
14
+
15
+ def convert(string)
16
+ " \u2022 #{string}"
17
+ end
18
+ end
19
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rb_markdown
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aurélien Delogu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-09 00:00:00.000000000 Z
11
+ date: 2026-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rb_monkey
@@ -24,17 +24,41 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.1.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rouge
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.30'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.30'
27
41
  description:
28
42
  email: aurelien.delogu@gmail.com
29
43
  executables: []
30
44
  extensions: []
31
45
  extra_rdoc_files: []
32
46
  files:
47
+ - src/markdown/abstract_line_tag.rb
33
48
  - src/markdown/abstract_tag.rb
49
+ - src/markdown/block_splitter.rb
34
50
  - src/markdown/bold_tag.rb
51
+ - src/markdown/code_block_renderer.rb
35
52
  - src/markdown/code_tag.rb
36
53
  - src/markdown/engine.rb
54
+ - src/markdown/heading_one_tag.rb
55
+ - src/markdown/heading_three_tag.rb
56
+ - src/markdown/heading_two_tag.rb
57
+ - src/markdown/inline_processor.rb
37
58
  - src/markdown/italic_tag.rb
59
+ - src/markdown/line_processor.rb
60
+ - src/markdown/ordered_list_tag.rb
61
+ - src/markdown/unordered_list_tag.rb
38
62
  - src/rb_markdown.rb
39
63
  homepage:
40
64
  licenses: []
@@ -54,8 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
54
78
  - !ruby/object:Gem::Version
55
79
  version: '0'
56
80
  requirements: []
57
- rubyforge_project:
58
- rubygems_version: 2.6.14.4
81
+ rubygems_version: 3.0.3.1
59
82
  signing_key:
60
83
  specification_version: 4
61
84
  summary: A tiny markdown engine