codeless_code 0.1.8 → 0.2.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
  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