rosetta-ruby 0.0.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.
Files changed (51) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +58 -0
  4. data/.rubocop.yml +8 -0
  5. data/.vscode/settings.json +3 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +16 -0
  8. data/README.md +48 -0
  9. data/TODOS.md +11 -0
  10. data/lib/rosetta/abstract_syntax_tree.rb +28 -0
  11. data/lib/rosetta/formatters/html/html_generator.rb +96 -0
  12. data/lib/rosetta/formatters/html/html_writer.rb +19 -0
  13. data/lib/rosetta/service_base.rb +8 -0
  14. data/lib/rosetta/services/inline_token_resolver.rb +80 -0
  15. data/lib/rosetta/services/input_scanner.rb +15 -0
  16. data/lib/rosetta/services/token_resolver.rb +42 -0
  17. data/lib/rosetta/services/tree_parser.rb +126 -0
  18. data/lib/rosetta/tokens/basic_list.rb +10 -0
  19. data/lib/rosetta/tokens/basic_list_item.rb +19 -0
  20. data/lib/rosetta/tokens/basic_token.rb +51 -0
  21. data/lib/rosetta/tokens/block_quote.rb +10 -0
  22. data/lib/rosetta/tokens/block_token.rb +36 -0
  23. data/lib/rosetta/tokens/bold.rb +21 -0
  24. data/lib/rosetta/tokens/break.rb +20 -0
  25. data/lib/rosetta/tokens/code_block.rb +10 -0
  26. data/lib/rosetta/tokens/code_block_delimiter.rb +18 -0
  27. data/lib/rosetta/tokens/header.rb +42 -0
  28. data/lib/rosetta/tokens/inline_code.rb +25 -0
  29. data/lib/rosetta/tokens/italics.rb +21 -0
  30. data/lib/rosetta/tokens/line_break.rb +18 -0
  31. data/lib/rosetta/tokens/link.rb +66 -0
  32. data/lib/rosetta/tokens/new_line.rb +20 -0
  33. data/lib/rosetta/tokens/numbered_list.rb +10 -0
  34. data/lib/rosetta/tokens/numbered_list_item.rb +25 -0
  35. data/lib/rosetta/tokens/paragraph.rb +10 -0
  36. data/lib/rosetta/tokens/quote.rb +24 -0
  37. data/lib/rosetta/tokens/shared/inline_tokens.rb +30 -0
  38. data/lib/rosetta/tokens/strikethrough.rb +29 -0
  39. data/lib/rosetta/tokens/text.rb +14 -0
  40. data/lib/rosetta-ruby.rb +15 -0
  41. data/main.rb +21 -0
  42. data/rosetta-ruby.gemspec +16 -0
  43. data/samples/all.md +50 -0
  44. data/samples/bold.md +1 -0
  45. data/samples/code_blocks.md +5 -0
  46. data/samples/headers.md +11 -0
  47. data/samples/link.md +3 -0
  48. data/samples/lists.md +10 -0
  49. data/samples/quotes.md +6 -0
  50. data/samples/text.md +5 -0
  51. metadata +91 -0
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/basic_token'
4
+
5
+ # Handles logic for Link tokens
6
+ class Link < BasicToken
7
+ def self.matches?(text)
8
+ # Naive check for link.
9
+ return false unless text.start_with?('[')
10
+
11
+ closing_bracket_index = text.index(']')
12
+ return false if closing_bracket_index.nil?
13
+
14
+ return false if text[closing_bracket_index + 1] != '('
15
+
16
+ text[closing_bracket_index + 1..].include?(')')
17
+ end
18
+
19
+ def self.consume(text)
20
+ closing_index = text.rindex(')')
21
+ source = text[0..closing_index]
22
+
23
+ new(source)
24
+ end
25
+
26
+ def to_s
27
+ "<Token type='#{type}' value='#{value}' url='#{url}'>"
28
+ end
29
+
30
+ def node_representation
31
+ "<#{type} value='#{value}' url='#{url}'>"
32
+ end
33
+
34
+ def type
35
+ :LINK
36
+ end
37
+
38
+ def value
39
+ final_bracket_index = url_beginning_index - 1
40
+
41
+ # We want the value inside brackets, and should exclude the brackets themselves.
42
+ @source_text[1...final_bracket_index]
43
+ end
44
+
45
+ def url
46
+ # We want the value inside the parenthesis, and should exclude the the parens themselves.
47
+ @source_text[url_beginning_index + 1...-1]
48
+ end
49
+
50
+ private
51
+
52
+ def url_beginning_index
53
+ open_bracket_count = 0
54
+
55
+ @url_beginning_index ||= @source_text.each_char.with_index do |character, index|
56
+ case character
57
+ when '['
58
+ open_bracket_count += 1
59
+ when ']'
60
+ open_bracket_count -= 1
61
+ end
62
+
63
+ return index + 1 if open_bracket_count.zero?
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/basic_token'
4
+
5
+ # Handles logic for New Line tokens
6
+ class NewLine < BasicToken
7
+ def self.matches?(text)
8
+ text == ''
9
+ end
10
+
11
+ def initialize; end
12
+
13
+ def type
14
+ :NEW_LINE
15
+ end
16
+
17
+ def value
18
+ nil
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/block_token'
4
+
5
+ # Handles logic for Paragraph tokens
6
+ class NumberedList < BlockToken
7
+ def type
8
+ :NUMBERED_LIST
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/basic_token'
4
+
5
+ # Handles logic for Header tokens
6
+ class NumberedListItem < BasicToken
7
+ def self.matches?(text)
8
+ return false unless number?(text[0])
9
+
10
+ text[1..2] == '. '
11
+ end
12
+
13
+ def type
14
+ :NUMBERED_LIST_ITEM
15
+ end
16
+
17
+ def value
18
+ # If the code reaches here we know the first 3 chars are the list delimiter.
19
+ @source_text[3..-1]
20
+ end
21
+
22
+ def self.number?(object)
23
+ object.to_s == object.to_i.to_s
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/block_token'
4
+
5
+ # Handles logic for Paragraph tokens
6
+ class Paragraph < BlockToken
7
+ def type
8
+ :PARAGRAPH
9
+ end
10
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/basic_token'
4
+
5
+ # Handles logic for Header tokens
6
+ class Quote < BasicToken
7
+ def self.matches?(text)
8
+ text.start_with?('> ')
9
+ end
10
+
11
+ def type
12
+ :QUOTE
13
+ end
14
+
15
+ def value
16
+ @value ||= extract_value_from_text
17
+ end
18
+
19
+ private
20
+
21
+ def extract_value_from_text
22
+ @source_text.delete_prefix('> ')
23
+ end
24
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Shared
4
+ # Handles logic for class methods for Inline Tokens.
5
+ module InlineTokens
6
+ def delimiter_length
7
+ delimiter_token.length
8
+ end
9
+
10
+ def matches?(text)
11
+ text.start_with?(delimiter_token) && valid_delimiter?(text[delimiter_length..])
12
+ end
13
+
14
+ def valid_delimiter?(text)
15
+ delimiter_index = text.index(delimiter_token)
16
+ !delimiter_index.nil?
17
+ end
18
+
19
+ def consume(text)
20
+ delimiter_index = text[delimiter_length..].index(delimiter_token) + delimiter_length
21
+
22
+ source = text[0..delimiter_index]
23
+ new(source)
24
+ end
25
+
26
+ def delimiter_token
27
+ const_get('DELIMITER_TOKEN')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/basic_token'
4
+ require './lib/rosetta/tokens/shared/inline_tokens'
5
+
6
+ # Handles logic for Strikethrough tokens
7
+ class Strikethrough < BasicToken
8
+ extend Shared::InlineTokens
9
+
10
+ DELIMITER_TOKEN = '~~'
11
+
12
+ def self.consume(raw_text)
13
+ # Add an extra 1 to offset the extra delimiter length (because strikethrough).
14
+ delimiter_index = raw_text[delimiter_length..].index(DELIMITER_TOKEN) + delimiter_length + 1
15
+
16
+ source = raw_text[0..delimiter_index]
17
+ new(source)
18
+ end
19
+
20
+ def type
21
+ :STRIKETHROUGH
22
+ end
23
+
24
+ def value
25
+ return DELIMITER_TOKEN * 2 if @source_text == DELIMITER_TOKEN * 2
26
+
27
+ @source_text[self.class.delimiter_length...-self.class.delimiter_length]
28
+ end
29
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/tokens/basic_token'
4
+
5
+ # Handles logic for Text tokens.
6
+ class Text < BasicToken
7
+ def type
8
+ :TEXT
9
+ end
10
+
11
+ def value
12
+ @source_text
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/abstract_syntax_tree'
4
+ require './lib/rosetta/formatters/html/html_writer'
5
+ require './lib/rosetta/services/input_scanner'
6
+
7
+ # Entry point for rosetta-ruby gem.
8
+ class Rosetta
9
+ def self.markdown_to_html(markdown_source)
10
+ source_tokens = InputScanner.call(markdown_source)
11
+ abstract_syntax_tree = AbstractSyntaxTree.new(source_tokens)
12
+
13
+ HTMLWriter.call(abstract_syntax_tree.token_tree)
14
+ end
15
+ end
data/main.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require './lib/rosetta/abstract_syntax_tree'
4
+ require './lib/rosetta/formatters/html/html_writer'
5
+ require './lib/rosetta/services/input_scanner'
6
+
7
+ # We ignore the issue of large file sizes for now.
8
+ # TODO: Optimise file reading, i.e. stream input for large source files.
9
+
10
+ puts 'Correct usage: ruby main.rb <source_filename>' if ARGV.length != 1
11
+
12
+ source_filename = ARGV[0]
13
+ source_file = File.read(source_filename)
14
+
15
+ source_tokens = InputScanner.call(source_file)
16
+
17
+ abstract_syntax_tree = AbstractSyntaxTree.new(source_tokens)
18
+
19
+ html_output = HTMLWriter.call(abstract_syntax_tree.token_tree)
20
+
21
+ puts html_output
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'rosetta-ruby'
5
+ spec.version = '0.0.0'
6
+ spec.summary = 'Rosetta'
7
+ spec.description = 'Simple Markdown to HTML transformation.'
8
+ spec.authors = ['Matt Craig']
9
+ spec.email = 'mattcraig365@gmail.com'
10
+ spec.files = `git ls-files`.split("\n")
11
+ spec.homepage = 'https://rubygems.org/gems/rosetta-ruby'
12
+ spec.license = 'MIT'
13
+ spec.required_ruby_version = '>= 3.0.0'
14
+
15
+ # spec.add_development_dependency ['rspec', 'byebug']
16
+ end
data/samples/all.md ADDED
@@ -0,0 +1,50 @@
1
+ # Testing all block features
2
+
3
+ ## Code Blocks
4
+
5
+ ```
6
+ def test
7
+ return true
8
+ end
9
+ ```
10
+
11
+ This is *bold text*!
12
+ *But* should all be part of the same paragraph.
13
+
14
+ This is _italicized text_!
15
+
16
+ This is ~~struck through~~!
17
+
18
+ This is an [inline) link](https://mattcraig.me)!
19
+
20
+ This is `inline code`!
21
+
22
+ ## Links
23
+
24
+ [A link.](https://example.com)
25
+
26
+ ## Quotes
27
+
28
+ > I'd rather be eating tacos.
29
+ > And writing quotes, of course.
30
+
31
+ In the middle of everything, some text!
32
+
33
+ ## Bullet List
34
+
35
+ - Thing 1
36
+ - Thing 2
37
+ - Thing 3
38
+
39
+ ## Another Bullet List
40
+
41
+ - A simple list
42
+ - With two items
43
+
44
+ More text!
45
+
46
+ ## Ordered List
47
+
48
+ 1. Order one
49
+ 2. Order two
50
+ 3. Order three
data/samples/bold.md ADDED
@@ -0,0 +1 @@
1
+ *This is* too.
@@ -0,0 +1,5 @@
1
+ ```
2
+ def test
3
+ return true
4
+ end
5
+ ```
@@ -0,0 +1,11 @@
1
+ # Header One
2
+
3
+ ## Header Two
4
+
5
+ ### Header Three
6
+
7
+ #### Header Four
8
+
9
+ ##### Header Five
10
+
11
+ ###### Header Six
data/samples/link.md ADDED
@@ -0,0 +1,3 @@
1
+ This line contains [a link](https://example.com) to a website.
2
+
3
+ [A link.](https://example.com)
data/samples/lists.md ADDED
@@ -0,0 +1,10 @@
1
+ 1. Number one
2
+ 2. Number two
3
+ 3. Three
4
+ 4. And so on..
5
+
6
+ - A simple list
7
+ - With two items
8
+
9
+ * Another simple list
10
+ * with two items
data/samples/quotes.md ADDED
@@ -0,0 +1,6 @@
1
+ # Paragraph One
2
+ This is a line of text.
3
+ > This is a quote
4
+ This is not a quote
5
+
6
+ >This is a quote again.
data/samples/text.md ADDED
@@ -0,0 +1,5 @@
1
+ # Paragraph One
2
+ This is a line of text.
3
+ This is another one.
4
+
5
+ This is yet another one.
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rosetta-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Matt Craig
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-08-30 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Simple Markdown to HTML transformation.
14
+ email: mattcraig365@gmail.com
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - ".DS_Store"
20
+ - ".gitignore"
21
+ - ".rubocop.yml"
22
+ - ".vscode/settings.json"
23
+ - Gemfile
24
+ - Gemfile.lock
25
+ - README.md
26
+ - TODOS.md
27
+ - lib/rosetta-ruby.rb
28
+ - lib/rosetta/abstract_syntax_tree.rb
29
+ - lib/rosetta/formatters/html/html_generator.rb
30
+ - lib/rosetta/formatters/html/html_writer.rb
31
+ - lib/rosetta/service_base.rb
32
+ - lib/rosetta/services/inline_token_resolver.rb
33
+ - lib/rosetta/services/input_scanner.rb
34
+ - lib/rosetta/services/token_resolver.rb
35
+ - lib/rosetta/services/tree_parser.rb
36
+ - lib/rosetta/tokens/basic_list.rb
37
+ - lib/rosetta/tokens/basic_list_item.rb
38
+ - lib/rosetta/tokens/basic_token.rb
39
+ - lib/rosetta/tokens/block_quote.rb
40
+ - lib/rosetta/tokens/block_token.rb
41
+ - lib/rosetta/tokens/bold.rb
42
+ - lib/rosetta/tokens/break.rb
43
+ - lib/rosetta/tokens/code_block.rb
44
+ - lib/rosetta/tokens/code_block_delimiter.rb
45
+ - lib/rosetta/tokens/header.rb
46
+ - lib/rosetta/tokens/inline_code.rb
47
+ - lib/rosetta/tokens/italics.rb
48
+ - lib/rosetta/tokens/line_break.rb
49
+ - lib/rosetta/tokens/link.rb
50
+ - lib/rosetta/tokens/new_line.rb
51
+ - lib/rosetta/tokens/numbered_list.rb
52
+ - lib/rosetta/tokens/numbered_list_item.rb
53
+ - lib/rosetta/tokens/paragraph.rb
54
+ - lib/rosetta/tokens/quote.rb
55
+ - lib/rosetta/tokens/shared/inline_tokens.rb
56
+ - lib/rosetta/tokens/strikethrough.rb
57
+ - lib/rosetta/tokens/text.rb
58
+ - main.rb
59
+ - rosetta-ruby.gemspec
60
+ - samples/all.md
61
+ - samples/bold.md
62
+ - samples/code_blocks.md
63
+ - samples/headers.md
64
+ - samples/link.md
65
+ - samples/lists.md
66
+ - samples/quotes.md
67
+ - samples/text.md
68
+ homepage: https://rubygems.org/gems/rosetta-ruby
69
+ licenses:
70
+ - MIT
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: 3.0.0
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubygems_version: 3.2.3
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: Rosetta
91
+ test_files: []