markdownlyze 0.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2893ad36d725df82ee075003813643374a0a6b612ba5f31595f4f3b889952ea1
4
+ data.tar.gz: 730467d9ad5ca5ed36bfb79e6a583e275a53d599da4cc1eedc9583775bdd7f03
5
+ SHA512:
6
+ metadata.gz: b2999d43f01fe126efbd00ed2c86b258bbcf1726c76c27228aca2d45376cbace5b5ec2d2b8cb854617932413896867992777a993bfa49794e4485d2e283a2b01
7
+ data.tar.gz: 1c159cf78113b05268a0bd56db22678ba8eeaffcf00a55723a50ef329a37e2af2f3cc3f584e60beb1e1a8a63e497822588b7517cb2f4b3a789c4970d65f96228
@@ -0,0 +1,39 @@
1
+ module Markdownlyze
2
+ class ElementNameMatcher
3
+ MATCHERS = {
4
+ /^# .*/ => :h1,
5
+ /^## .*/ => :h2,
6
+ /^### .*/ => :h3,
7
+ /^#### .*/ => :h4,
8
+ /\!\[.*\]\(\.\/images\/.*\)/ => :image,
9
+ /```[a-z]*/ => :code_block,
10
+ /^\> .*/ => :quote,
11
+ [/^1\. .*/, lambda { |next_line| next_line.to_s.match?(/^2\. .*/) }] => :ol,
12
+ [/^(\*|\-) .*/, lambda { |next_line| next_line.to_s.match?(/^(\*|\-) .*/) }] => :ul,
13
+ [/^|.* \| .*$/, lambda { |next_line| next_line.to_s.count('|') > 1 }] => :table
14
+ }.freeze
15
+
16
+ class << self
17
+ def call(current_line:, next_line:)
18
+ return :blank_line if current_line.nil? || current_line.strip.empty?
19
+
20
+ MATCHERS.each do |pattern, element|
21
+ return element if matching?(current_line, next_line, pattern)
22
+ end
23
+
24
+ :paragraph
25
+ end
26
+
27
+ private
28
+
29
+ def matching?(current_line, next_line, pattern)
30
+ if pattern.is_a?(Regexp)
31
+ current_line.match?(pattern)
32
+ else
33
+ regex_pattern, lambda_pattern = pattern
34
+ current_line.match?(regex_pattern) && lambda_pattern.call(next_line)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,40 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Base
4
+ attr_reader :skip_until
5
+
6
+ def initialize(line:, index:, lines:)
7
+ @line = line
8
+ @index = index
9
+ @lines = lines
10
+ @skip_until = nil
11
+ end
12
+
13
+ def options = {}
14
+
15
+ private
16
+
17
+ def to_html(value)
18
+ # avoid case when 1. something is created as one element ol list
19
+ if value.to_s.match?(/^\d+\. .*/)
20
+ captures = value.match(/^(?<start_number>\d+)\. (?<raw_value>.*)/).named_captures
21
+ parsed_value = markdown.render(captures.fetch('raw_value')).gsub(/\<(|\/)p\>/, '').gsub("\n", '').gsub("&#39;", "'")
22
+ element_number = captures.fetch('start_number')
23
+
24
+ "#{element_number}. #{parsed_value}"
25
+ elsif value.to_s.strip == '>'
26
+ ''
27
+ else
28
+ markdown.render(value).gsub(/\<(|\/)p\>/, '').gsub("\n", '').gsub("&#39;", "'")
29
+ end
30
+ end
31
+
32
+ def markdown
33
+ @markdown ||= begin
34
+ renderer = Redcarpet::Render::HTML.new(render_options = {})
35
+ Redcarpet::Markdown.new(renderer, extensions = {})
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class BlankLine < ::Markdownlyze::Elements::Base
4
+ def value = nil
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class CodeBlock < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @lines[@index..-1].each_with_index do |subline, subindex|
6
+ if subline.to_s.strip == '```'
7
+ @skip_until = @index + subindex + 1
8
+ break
9
+ end
10
+ end
11
+
12
+ @lines[(@index + 1)..(@skip_until - 2)].join("\n")
13
+ end
14
+
15
+ def options
16
+ { language: language }
17
+ end
18
+
19
+ private
20
+
21
+ def language
22
+ (@line.match(/```(?<language>[a-z].*)/) || { language: 'bash' })[:language]
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class H1 < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @line.gsub(/^# /, '')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class H2 < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @line.gsub(/^## /, '')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class H3 < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @line.gsub(/^### /, '')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class H4 < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @line.gsub(/^#### /, '')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Image < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @line.match(/\!\[.*\]\((?<file_name>.*)\)/).named_captures.fetch('file_name')
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Ol < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @lines[@index..-1].each_with_index do |subline, subindex|
6
+ if !subline.match?(/^\d+\. .*/)
7
+ @skip_until = @index + subindex
8
+ break
9
+ end
10
+ end
11
+
12
+ @skip_until = @lines.size if @skip_until.nil?
13
+
14
+ @lines[@index..(@skip_until - 1)].map { |line| to_html(line.gsub(/^\d+\. /, '')) }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Paragraph < ::Markdownlyze::Elements::Base
4
+ def value = to_html(@line)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Quote < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @lines[@index..-1].each_with_index do |subline, subindex|
6
+ if !subline.match?(/^\> .*/) && subline.to_s.strip != '>'
7
+ @skip_until = @index + subindex
8
+ break
9
+ end
10
+ end
11
+
12
+ @skip_until = @lines.size if @skip_until.nil?
13
+
14
+ @lines[@index..(@skip_until - 1)].map { |line| to_html(line.gsub(/^\> /, '')) }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Table < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @lines[@index..-1].each_with_index do |subline, subindex|
6
+ if subline.count('|') < 2
7
+ @skip_until = @index + subindex
8
+ break
9
+ end
10
+ end
11
+
12
+ table_lines = @lines[@index..(skip_until.to_i - 1)]
13
+ headers = table_lines.shift
14
+ table_lines.shift
15
+ raw_table = [headers] | table_lines
16
+ rows = raw_table.map { |row| row.split("|").map(&:strip)[1..-1].map { |value| to_html(value) } }
17
+
18
+ if @skip_until.to_i.zero?
19
+ @skip_until = @index + rows.size + 1
20
+ end
21
+
22
+ rows
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module Markdownlyze
2
+ module Elements
3
+ class Ul < ::Markdownlyze::Elements::Base
4
+ def value
5
+ @lines[@index..-1].each_with_index do |subline, subindex|
6
+ if !subline.match?(/^(\*|\-) .*/)
7
+ @skip_until = @index + subindex
8
+ break
9
+ end
10
+ end
11
+
12
+ @skip_until = @lines.size if @skip_until.nil?
13
+
14
+ @lines[@index..(@skip_until - 1)].map { |line| to_html(line.gsub(/^(\*|\-) /, '')) }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module Markdownlyze
2
+ module Version
3
+ module_function
4
+
5
+ def to_s
6
+ "0.0.2"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,54 @@
1
+ require 'redcarpet'
2
+
3
+ require_relative 'markdownlyze/element_name_matcher'
4
+
5
+ require_relative 'markdownlyze/elements/base'
6
+ require_relative 'markdownlyze/elements/h1'
7
+ require_relative 'markdownlyze/elements/h2'
8
+ require_relative 'markdownlyze/elements/h3'
9
+ require_relative 'markdownlyze/elements/h4'
10
+ require_relative 'markdownlyze/elements/image'
11
+ require_relative 'markdownlyze/elements/blank_line'
12
+ require_relative 'markdownlyze/elements/paragraph'
13
+ require_relative 'markdownlyze/elements/code_block'
14
+ require_relative 'markdownlyze/elements/table'
15
+ require_relative 'markdownlyze/elements/ol'
16
+ require_relative 'markdownlyze/elements/ul'
17
+ require_relative 'markdownlyze/elements/quote'
18
+
19
+ module Markdownlyze
20
+ class << self
21
+ def parse(content)
22
+ markdown_lines = content.to_s.split("\n")
23
+ skip_until = nil
24
+
25
+ elements = markdown_lines.map.with_index do |line, index|
26
+ unless skip_until.nil?
27
+ next if index < skip_until
28
+ end
29
+
30
+ element_name = ::Markdownlyze::ElementNameMatcher.call(
31
+ current_line: line,
32
+ next_line: markdown_lines[index + 1]
33
+ )
34
+
35
+ element_class = ::Markdownlyze::Elements.const_get(element_name.to_s.split('_').map(&:capitalize).join)
36
+ element = element_class.new(
37
+ line: line,
38
+ index: index,
39
+ lines: markdown_lines
40
+ )
41
+
42
+ { element: element_name, value: element.value }.merge(element.options).tap do
43
+ skip_until = element.skip_until
44
+ end
45
+ end
46
+
47
+ elements.compact
48
+ end
49
+
50
+ def parse_file(file_path)
51
+ parse(File.read(file_path))
52
+ end
53
+ end
54
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: markdownlyze
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Paweł Dąbrowski
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-08-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: redcarpet
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.6.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.6.0
55
+ description: Turn markdown documents into easily parseable format
56
+ email: contact@paweldabrowski.com
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - lib/markdownlyze.rb
62
+ - lib/markdownlyze/element_name_matcher.rb
63
+ - lib/markdownlyze/elements/base.rb
64
+ - lib/markdownlyze/elements/blank_line.rb
65
+ - lib/markdownlyze/elements/code_block.rb
66
+ - lib/markdownlyze/elements/h1.rb
67
+ - lib/markdownlyze/elements/h2.rb
68
+ - lib/markdownlyze/elements/h3.rb
69
+ - lib/markdownlyze/elements/h4.rb
70
+ - lib/markdownlyze/elements/image.rb
71
+ - lib/markdownlyze/elements/ol.rb
72
+ - lib/markdownlyze/elements/paragraph.rb
73
+ - lib/markdownlyze/elements/quote.rb
74
+ - lib/markdownlyze/elements/table.rb
75
+ - lib/markdownlyze/elements/ul.rb
76
+ - lib/markdownlyze/version.rb
77
+ homepage:
78
+ licenses: []
79
+ metadata: {}
80
+ post_install_message:
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.4.10
96
+ signing_key:
97
+ specification_version: 4
98
+ summary: Turn markdown documents into easily parseable format
99
+ test_files: []