codeless_code 0.1.8 → 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
2
  SHA256:
3
- metadata.gz: 5154091052ec2023109ecdc022ec10fdfa3762dcec89f1dd2f6203acac57018d
4
- data.tar.gz: f9eb3c12e08dd25885faf6d758d67e1020d324a8ce53ab7c77b486b001eeceb1
3
+ metadata.gz: c894ee4dd542acaa1728467fed14bb268637e7ff83b879b124f2b1c7648822f4
4
+ data.tar.gz: 0a7e08880e5a9f3391602f0a78519456f82b3dff75128ddc72ca50e043355d04
5
5
  SHA512:
6
- metadata.gz: bba85e6463c19551a62b0064af87905f0bc1781bcaf198591c2513b4157ae514cc0fd17e31da864683be25c599c7d4170250ecfee8a098c45df9caab6d40600d
7
- data.tar.gz: 4d8b4f45d6511bac204a88bb5b936a5303da0d5bbed221bdfa0531e03ee45193bcce7ae3f959c5d3c1b41f8ea75359598a5d010a09e98393dfa57dfd9a1de525
6
+ metadata.gz: 7f3696c7bdaafdd0da45751f727c48c1a2cf1aa258a66a5f430f759d09514c67f81f7dca8641d1a4f4d4ae645090561ea25346e5d4b4e6978c4a900b6c35b076
7
+ data.tar.gz: d5c134eac07fb092af685b8e547e07447b72d99301ae225b60168c3c4ef6232a755b699f7e66e2873f3ff8aef9cd9a203c97a9c10d04c6f9d5d9182f34965af8
data/.gitmodules CHANGED
@@ -1,3 +1,3 @@
1
1
  [submodule "data/the-codeless-code"]
2
- path = data/the-codeless-code
2
+ path = data
3
3
  url = https://github.com/sangster/the-codeless-code.git
data/.reek.yml CHANGED
@@ -8,6 +8,8 @@ detectors:
8
8
  enabled: false
9
9
  LongParameterList:
10
10
  max_params: 4
11
+ RepeatedConditional:
12
+ enabled: false
11
13
  UtilityFunction:
12
14
  exclude:
13
15
  - CodelessCode::Filters::Headers::Base
data/Gemfile CHANGED
@@ -18,7 +18,6 @@
18
18
  source 'https://rubygems.org'
19
19
 
20
20
  gem 'colorize', '~> 0.8'
21
- gem 'mediacloth', '~> 0.6'
22
21
  gem 'nokogiri', '~> 1.8'
23
22
  gem 'slop', '~> 4.6'
24
23
 
data/Gemfile.lock CHANGED
@@ -74,7 +74,6 @@ GEM
74
74
  rb-inotify (~> 0.9, >= 0.9.7)
75
75
  ruby_dep (~> 1.2)
76
76
  lumberjack (1.0.13)
77
- mediacloth (0.6)
78
77
  method_source (0.9.0)
79
78
  mime-types (2.99.3)
80
79
  mini_portile2 (2.3.0)
@@ -161,7 +160,6 @@ DEPENDENCIES
161
160
  guard-reek (~> 1.2)
162
161
  guard-rubocop (~> 1.3)
163
162
  jeweler (~> 2.0)
164
- mediacloth (~> 0.6)
165
163
  minitest (~> 5.11)
166
164
  minitest-reporters (~> 1.3)
167
165
  nokogiri (~> 1.8)
data/Guardfile CHANGED
@@ -1,6 +1,6 @@
1
+ # vim:ft=ruby:
1
2
  # frozen_string_literal: true
2
3
 
3
- # vim:ft=ruby:
4
4
  # codeless_code filters and prints fables from http://thecodelesscode.com
5
5
  # Copyright (C) 2018 Jon Sangster
6
6
  #
@@ -16,18 +16,20 @@
16
16
  #
17
17
  # You should have received a copy of the GNU General Public License along with
18
18
  # this program. If not, see <https://www.gnu.org/licenses/>.
19
- guard :minitest, all_after_pass: true do
20
- watch(%r{^test/(.*)\/?test_(.*)\.rb$})
21
- watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
22
- watch(%r{^test/helper\.rb$}) { 'test' }
23
- end
19
+ group :everything, halt_on_fail: true do
20
+ guard :minitest, all_after_pass: true do
21
+ watch(%r{^test/(.*)\/?test_(.*)\.rb$})
22
+ watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
23
+ watch(%r{^test/helper\.rb$}) { 'test' }
24
+ end
24
25
 
25
- guard :reek do
26
- watch(%r{^lib/.+\.rb$})
27
- watch('.reek.yml')
28
- end
26
+ guard :reek do
27
+ watch(%r{^lib/.+\.rb$})
28
+ watch('.reek.yml')
29
+ end
29
30
 
30
- guard :rubocop do
31
- watch(/.+\.rb$/)
32
- watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
31
+ guard :rubocop do
32
+ watch(/.+\.rb$/)
33
+ watch(%r{(?:.+/)?\.rubocop(?:_todo)?\.yml$}) { |m| File.dirname(m[0]) }
34
+ end
33
35
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.2.0
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: codeless_code 0.1.8 ruby lib
5
+ # stub: codeless_code 0.2.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "codeless_code".freeze
9
- s.version = "0.1.8"
9
+ s.version = "0.2.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jon Sangster".freeze]
14
- s.date = "2018-11-09"
14
+ s.date = "2018-11-17"
15
15
  s.description = "http://thecodelesscode.com contains many humorous and interesting fables and koans. The authors have open-sourced these fables, and many tanslations, available at https://github.com/aldesantis/the-codeless-code. This tool provides a CLI to filter through these fables and view them.".freeze
16
16
  s.email = "jon@ertt.ca".freeze
17
17
  s.executables = ["codeless_code".freeze]
@@ -1495,13 +1495,13 @@ Gem::Specification.new do |s|
1495
1495
  "lib/codeless_code/filters/lang.rb",
1496
1496
  "lib/codeless_code/filters/translator.rb",
1497
1497
  "lib/codeless_code/formats/base.rb",
1498
- "lib/codeless_code/formats/parsers/base.rb",
1499
- "lib/codeless_code/formats/parsers/plain.rb",
1500
- "lib/codeless_code/formats/parsers/term.rb",
1501
1498
  "lib/codeless_code/formats/plain.rb",
1502
1499
  "lib/codeless_code/formats/raw.rb",
1503
1500
  "lib/codeless_code/formats/term.rb",
1504
1501
  "lib/codeless_code/language_set.rb",
1502
+ "lib/codeless_code/markup/converter.rb",
1503
+ "lib/codeless_code/markup/nodes.rb",
1504
+ "lib/codeless_code/markup/parser.rb",
1505
1505
  "lib/codeless_code/options.rb",
1506
1506
  "lib/codeless_code/renderers/fable.rb",
1507
1507
  "lib/codeless_code/renderers/term_page.rb",
@@ -1511,8 +1511,12 @@ Gem::Specification.new do |s|
1511
1511
  "test/codeless_code/filters/test_builders.rb",
1512
1512
  "test/codeless_code/filters/test_composite.rb",
1513
1513
  "test/codeless_code/filters/test_date.rb",
1514
- "test/codeless_code/filters/test_langs.rb",
1514
+ "test/codeless_code/filters/test_lang.rb",
1515
1515
  "test/codeless_code/filters/test_translator.rb",
1516
+ "test/codeless_code/formats/test_plain.rb",
1517
+ "test/codeless_code/formats/test_raw.rb",
1518
+ "test/codeless_code/formats/test_term.rb",
1519
+ "test/codeless_code/markup/test_parser.rb",
1516
1520
  "test/codeless_code/renderers/test_fable.rb",
1517
1521
  "test/codeless_code/renderers/test_term_page.rb",
1518
1522
  "test/codeless_code/test_catalog.rb",
@@ -1534,7 +1538,6 @@ Gem::Specification.new do |s|
1534
1538
 
1535
1539
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
1536
1540
  s.add_runtime_dependency(%q<colorize>.freeze, ["~> 0.8"])
1537
- s.add_runtime_dependency(%q<mediacloth>.freeze, ["~> 0.6"])
1538
1541
  s.add_runtime_dependency(%q<nokogiri>.freeze, ["~> 1.8"])
1539
1542
  s.add_runtime_dependency(%q<slop>.freeze, ["~> 4.6"])
1540
1543
  s.add_development_dependency(%q<bundler>.freeze, ["~> 1.17"])
@@ -1554,7 +1557,6 @@ Gem::Specification.new do |s|
1554
1557
  s.add_development_dependency(%q<yard>.freeze, ["~> 0.9"])
1555
1558
  else
1556
1559
  s.add_dependency(%q<colorize>.freeze, ["~> 0.8"])
1557
- s.add_dependency(%q<mediacloth>.freeze, ["~> 0.6"])
1558
1560
  s.add_dependency(%q<nokogiri>.freeze, ["~> 1.8"])
1559
1561
  s.add_dependency(%q<slop>.freeze, ["~> 4.6"])
1560
1562
  s.add_dependency(%q<bundler>.freeze, ["~> 1.17"])
@@ -1575,7 +1577,6 @@ Gem::Specification.new do |s|
1575
1577
  end
1576
1578
  else
1577
1579
  s.add_dependency(%q<colorize>.freeze, ["~> 0.8"])
1578
- s.add_dependency(%q<mediacloth>.freeze, ["~> 0.6"])
1579
1580
  s.add_dependency(%q<nokogiri>.freeze, ["~> 1.8"])
1580
1581
  s.add_dependency(%q<slop>.freeze, ["~> 4.6"])
1581
1582
  s.add_dependency(%q<bundler>.freeze, ["~> 1.17"])
@@ -51,4 +51,4 @@ aufgenommen werden können?"
51
51
  lieben?"
52
52
 
53
53
 
54
- {{*}} "Stealthy Wombat" spendete folgendes Gedicht:<p>Enkudu nahm zur Tausend-Meilen-Reise<br>Gehstock, Fisch -- und Navigationsgerät<br>wie glücklich die ersten zwei Schwestern,<br>dass Enkudu ihre Liebe nie schmäht.</p>
54
+ {{*}} "Stealthy Wombat" spendete folgendes Gedicht:<p>Enkudu nahm zur Tausend-Meilen-Reise<br>Gehstock, Fisch -- und Navigationsgerät<br>wie glücklich die ersten zwei Schwestern,<br>dass Enkudu ihre Liebe nie schmäht.
@@ -42,4 +42,4 @@ Schalen hässlich und seine Lager klein sind."
42
42
  ihrem Handtuch. "Nun sitzt er in einem Haufen Perlen, und hungert nach
43
43
  Austernfleisch."
44
44
 
45
- {{*}} "Stealthy Wombat" bietet uns dies Gedicht:<p> Yishi-Shing verliert seine Perle im Saal,<br> lässt Yíwen und Hwidah lang sie suchen,<br> Und Ahab quert die See, findet doch nicht den Wal,<br> und so bleibet ihm nichts als zu fluchen.</p>
45
+ {{*}} "Stealthy Wombat" bietet uns dies Gedicht:<p> Yishi-Shing verliert seine Perle im Saal,<br> lässt Yíwen und Hwidah lang sie suchen,<br> Und Ahab quert die See, findet doch nicht den Wal,<br> und so bleibet ihm nichts als zu fluchen.
@@ -86,4 +86,4 @@ between order and chaos."
86
86
 
87
87
  Hearing these words, Zjing was enlightened.
88
88
 
89
- {{*}} Translator Andre Bogus offers the following poem:<p>The herd was still, the cattle grazed<br>Zjing saw them and was amazed<br>How full of harmony those cows<br>unlike her monks the meadow browse</p>
89
+ {{*}} Translator Andre Bogus offers the following poem:<p>The herd was still, the cattle grazed<br>Zjing saw them and was amazed<br>How full of harmony those cows<br>unlike her monks the meadow browse
@@ -49,4 +49,4 @@ Hwídah from under her towel. 'Now, bedecked in orphan
49
49
  pearls, we will starve for want of oyster-meat."
50
50
 
51
51
 
52
- {{*}} "Stealthy Wombat" offers this poem:<p>Yíwen and Hwídah sift the yard for Yishi-Shing's pearl<br>In spring, he loses it again<br>Ahab searched the seas for the white whale<br>The whale was white, but oh! So broad the ocean!</p>
52
+ {{*}} "Stealthy Wombat" offers this poem:<p>Yíwen and Hwídah sift the yard for Yishi-Shing's pearl<br>In spring, he loses it again<br>Ahab searched the seas for the white whale<br>The whale was white, but oh! So broad the ocean!
@@ -32,7 +32,6 @@ module CodelessCode
32
32
  call_io(user_io)
33
33
  rescue Slop::Error => err
34
34
  warn format("%s\n\n%s", err, options.help)
35
- exit 1
36
35
  ensure
37
36
  user_io&.close
38
37
  end
@@ -98,6 +97,7 @@ module CodelessCode
98
97
  end
99
98
  end
100
99
 
100
+ # @return [Random] with a seed value determined by the current date
101
101
  # :reek:UtilityFunction
102
102
  def date_random_generator
103
103
  Random.new(::Date.today.strftime('%Y%m%d').to_i)
@@ -40,7 +40,7 @@ module CodelessCode
40
40
  @body_pos = 0
41
41
  end
42
42
 
43
- # @return [String] the actual story, including MediaWiki markup
43
+ # @return [String] the actual story, including markup
44
44
  def body
45
45
  @body ||= read_body.freeze
46
46
  end
@@ -15,7 +15,6 @@
15
15
  #
16
16
  # You should have received a copy of the GNU General Public License along with
17
17
  # this program. If not, see <https://www.gnu.org/licenses/>.
18
- require 'mediacloth'
19
18
  require 'nokogiri'
20
19
 
21
20
  module CodelessCode
@@ -30,24 +29,8 @@ module CodelessCode
30
29
 
31
30
  protected
32
31
 
33
- def from_wiki(doc, parser_name)
34
- parser = Parsers.const_get(parser_name).new(self)
35
- MediaCloth.wiki_to_html(doc.to_s, generator: parser)
36
- end
37
- end
38
-
39
- # MediaCloth expects XHTML-ish pages and chokes on ommited end tags
40
- class XhtmlDoc
41
- def self.parse(html)
42
- new(Nokogiri::HTML(html))
43
- end
44
-
45
- def initialize(doc)
46
- @doc = doc
47
- end
48
-
49
- def to_s
50
- @doc.css('body > *').to_xhtml
32
+ def render_children(node)
33
+ node.children.map(&method(:render)).join
51
34
  end
52
35
  end
53
36
  end
@@ -15,39 +15,52 @@
15
15
  #
16
16
  # You should have received a copy of the GNU General Public License along with
17
17
  # this program. If not, see <https://www.gnu.org/licenses/>.
18
- require 'mediacloth'
19
-
20
18
  module CodelessCode
21
19
  module Formats
22
20
  # Prints the {Fable} without any formatting, but removes the markup.
23
21
  class Plain < Base
22
+ include Markup::Nodes
23
+
24
24
  def call
25
- raw.split("\n\n")
26
- .map { |str| from_wiki(CleanupBody.new(str)) }
27
- .join("\n\n")
25
+ main = Markup::Parser.new(raw).call
26
+ render(Markup::Converter.new(main).call).rstrip
28
27
  end
29
28
 
30
- protected
29
+ private
31
30
 
32
- def from_wiki(str)
33
- super(XhtmlDoc.parse(str.to_s), :Plain)
31
+ def render(node)
32
+ render_leaf(node) || render_container(node) ||
33
+ raise(format('Unexpected %s: %p', node.class, node))
34
+ end
35
+
36
+ # :reek:UtilityFunction
37
+ def render_leaf(node)
38
+ case node
39
+ when String then node
40
+ when LineBreak then "\n"
41
+ when Rule then '- - - - - - - - -' + "\n\n"
42
+ end
43
+ end
44
+
45
+ def render_container(node)
46
+ case node
47
+ when Doc, Bold, Em, Link then render_children(node)
48
+ when Reference then format('[%s]', render_children(node))
49
+ when Header then render_header(node)
50
+ when Para then render_children(node) + "\n\n"
51
+ when Quote then render_quote(node)
52
+ end
34
53
  end
35
- end
36
54
 
37
- # Tidies up the mixed syntax found in fables
38
- class CleanupBody
39
- def initialize(body)
40
- @body = body
55
+ def render_header(node)
56
+ inner = render_children(node)
57
+ format("%s\n%s", inner, '-' * inner.length) + "\n\n"
41
58
  end
42
59
 
43
- def to_s
44
- [
45
- [%r{//\w*$}, ''],
46
- [%r{<i>([^<]+)</i>}mi, '\1'],
47
- [%r{<b>([^<]+)</b>}mi, '\1'],
48
- [%r{<a[^>]+>([^<]+)</a>}mi, '\1'],
49
- [%r{/(\w+)/}, '\1']
50
- ].inject(@body) { |str, args| str.gsub(*args) }
60
+ def render_quote(node)
61
+ render_children(node).lines
62
+ .map { |line| "\t" + line }
63
+ .join + "\n\n"
51
64
  end
52
65
  end
53
66
  end
@@ -16,39 +16,69 @@
16
16
  # You should have received a copy of the GNU General Public License along with
17
17
  # this program. If not, see <https://www.gnu.org/licenses/>.
18
18
  require 'colorized_string'
19
- require 'mediacloth'
20
19
 
21
20
  module CodelessCode
22
21
  module Formats
23
22
  # Renders the {Fable} using ANSI control characters for bold, italics,
24
23
  # colors, etc.
25
24
  class Term < Base
25
+ include Markup::Nodes
26
+
26
27
  def call
27
- from_wiki
28
+ render(
29
+ Markup::Converter.new(
30
+ Markup::Parser.new(raw).call
31
+ ).call
32
+ ).strip
28
33
  end
29
34
 
30
- # :reek:UtilityFunction
31
- def color(str)
32
- ColorizedString.new(str)
35
+ private
36
+
37
+ def render(node)
38
+ render_leaf(node) || render_container(node) || render_style(node) ||
39
+ raise(format('Unexpected %s: %p', node.class, node))
33
40
  end
34
41
 
35
- protected
42
+ def render_leaf(node)
43
+ case node
44
+ when String then node
45
+ when LineBreak then "\n"
46
+ when Rule then format("%s\n\n", color('- - - - - - - - -').yellow)
47
+ end
48
+ end
36
49
 
37
- def from_wiki
38
- super(XhtmlDoc.parse(regex_raw), :Term)
50
+ def render_style(node)
51
+ case node
52
+ when Bold then color(render_children(node)).bold
53
+ when Em then color(render_children(node)).italic
54
+ when Reference then color(render_children(node)).yellow
55
+ end
39
56
  end
40
57
 
41
- private
58
+ def render_container(node)
59
+ case node
60
+ when Doc then render_children(node)
61
+ when Header then render_header(node)
62
+ when Link then color(render_children(node)).underline
63
+ when Para then render_children(node) + "\n\n"
64
+ when Quote then render_quote(node)
65
+ end
66
+ end
67
+
68
+ def render_header(node)
69
+ inner = render_children(node)
70
+ color(format("%s\n%s", inner, '-' * inner.length)).blue + "\n\n"
71
+ end
42
72
 
43
- def regex_raw
44
- [
45
- [%r{//\w*$}, ''],
46
- [/^\| .*/, ColorizedString.new('\\0').green],
47
- [%r{<i>([^<]+)</i>}mi, "''\\1''"],
48
- [%r{<b>([^<]+)</b>}mi, "'''\\1'''"],
49
- [%r{<a[^>]+>([^<]+)</a>}mi, '[[\1]]'],
50
- [%r{/(\w+)/}, "''\\1''"]
51
- ].inject(raw) { |str, args| str.gsub(*args) }
73
+ def render_quote(node)
74
+ render_children(node).lines
75
+ .map { |line| "\t" + color(line).green }
76
+ .join + "\n\n"
77
+ end
78
+
79
+ # :reek:UtilityFunction
80
+ def color(str)
81
+ ColorizedString.new(str.to_s)
52
82
  end
53
83
  end
54
84
  end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ # codeless_code filters and prints fables from http://thecodelesscode.com
4
+ # Copyright (C) 2018 Jon Sangster
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program. If not, see <https://www.gnu.org/licenses/>.
18
+ module CodelessCode
19
+ module Markup
20
+ CONTAINER_HTML = {
21
+ 'blockquote' => Nodes::Quote,
22
+ 'b' => Nodes::Bold,
23
+ 'div' => Nodes::Para,
24
+ 'em' => Nodes::Em,
25
+ 'h2' => Nodes::Header,
26
+ 'i' => Nodes::Em,
27
+ 'main' => Nodes::Doc,
28
+ 'p' => Nodes::Para,
29
+ 'span' => Nodes::Para,
30
+ 'strong' => Nodes::Bold,
31
+ 'sup' => Nodes::Reference,
32
+ 'tt' => Nodes::Bold
33
+ }.freeze
34
+
35
+ # Converts {Nokogiri} elements to {Nodes::Node} elements
36
+ class Converter
37
+ def initialize(elem)
38
+ @elem = elem
39
+ end
40
+
41
+ # @return [Nodes::Node]
42
+ def call
43
+ convert_elem(@elem)
44
+ end
45
+
46
+ private
47
+
48
+ # :reek:FeatureEnvy
49
+ def convert_elem(elem)
50
+ if elem.text?
51
+ elem.content
52
+ elsif (type = CONTAINER_HTML[elem.name])
53
+ type.new(convert_children(elem))
54
+ else
55
+ convert_special(elem)
56
+ end
57
+ end
58
+
59
+ def convert_children(elem)
60
+ elem.children.map { |ch| self.class.new(ch).call }
61
+ end
62
+
63
+ def convert_special(elem)
64
+ case elem.name
65
+ when 'a' then convert_link(elem)
66
+ when 'br' then Nodes::LineBreak.new
67
+ when 'hr' then Nodes::Rule.new
68
+ else
69
+ raise format('Unexpected: %p', elem)
70
+ end
71
+ end
72
+
73
+ def convert_link(elem)
74
+ Nodes::Link.new(elem['href'], convert_children(elem))
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ # codeless_code filters and prints fables from http://thecodelesscode.com
4
+ # Copyright (C) 2018 Jon Sangster
5
+ #
6
+ # This program is free software: you can redistribute it and/or modify it under
7
+ # the terms of the GNU General Public License as published by the Free Software
8
+ # Foundation, either version 3 of the License, or (at your option) any later
9
+ # version.
10
+ #
11
+ # This program is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU General Public License along with
17
+ # this program. If not, see <https://www.gnu.org/licenses/>.
18
+ module CodelessCode
19
+ module Markup
20
+ # Elements representing the markup of a Fable
21
+ # :reek:ModuleInitialize
22
+ module Nodes
23
+ ELEM_CONTAINERS = %i[Doc Para Quote Bold Em Reference Header].freeze
24
+ ELEM_VOID = %i[LineBreak Rule].freeze
25
+
26
+ # An element in the syntax tree
27
+ class Node
28
+ def initialize(children = nil)
29
+ @children = children
30
+ end
31
+
32
+ def to_s
33
+ children.map(&:to_s).join
34
+ end
35
+
36
+ def children
37
+ @children || []
38
+ end
39
+ end
40
+
41
+ ELEM_CONTAINERS.each do |name|
42
+ const_set(name, Class.new(Node))
43
+ end
44
+
45
+ ELEM_VOID.each do |name|
46
+ const_set(name, Class.new(Node) do
47
+ def initialize
48
+ super()
49
+ end
50
+ end)
51
+ end
52
+
53
+ # A hyperlink. Either +<a href=""></a>+, +[[label]]+, or +[[url|label]]+
54
+ class Link < Node
55
+ attr_reader :href
56
+
57
+ def initialize(href = nil, children = [])
58
+ super(children)
59
+ @href = href
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end