hierogloss 0.0.1

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.
@@ -0,0 +1,55 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <%
6
+ # This code from Kramdown's default template.
7
+ extend ::Kramdown::Utils::Html
8
+ title = 'Hierogloss'
9
+ h = @converter.root.children.find {|c| c.type == :header}
10
+ if h
11
+ collector = lambda {|c| c.children.collect {|cc| cc.type == :text ? escape_html(cc.value, :text) : collector.call(cc)}.join('')}
12
+ title = collector.call(h)
13
+ end
14
+ %>
15
+ <title><%= title %></title>
16
+ <meta name="generator" content="hierogloss kramdown <%= ::Kramdown::VERSION %>" />
17
+
18
+ <style type="text/css">
19
+ @font-face {
20
+ font-family: 'WebGardiner';
21
+ src: url('fonts/Gardiner.eot');
22
+ src: local('☺'), url('fonts/Gardiner.woff') format('woff'), url('fonts/Gardiner.ttf') format('truetype'), url('fonts/Gardiner.svg') format('svg');
23
+ font-weight: normal;
24
+ font-style: normal;
25
+ }
26
+
27
+ .hgls-h, .hgls-l {
28
+ font-family: "WebGardiner", "Aegyptus", "Gardiner", serif;
29
+ }
30
+ .hgls-l { font-style: normal; font-size: 18pt; }
31
+ .hgls-h { font-size: 24px; }
32
+
33
+ .hgls-gloss td { padding-right: 18px; }
34
+ .hgls-gloss {
35
+ margin-left: 18px;
36
+ page-break-inside: avoid;
37
+ }
38
+ p.hgls-gloss {
39
+ margin-top: 0;
40
+ }
41
+ table.hgls-gloss a:link, table.hgls-gloss a:visited {
42
+ color: black;
43
+ text-decoration: none;
44
+ }
45
+ table.hgls-gloss a:hover {
46
+ text-decoration: underline;
47
+ }
48
+ </style>
49
+ </head>
50
+ <body>
51
+
52
+ <%= @body %>
53
+
54
+ </body>
55
+ </html>
@@ -0,0 +1,13 @@
1
+ # Disjunction in Middle Egyptian
2
+
3
+ This example is based on one in Allen's excellent [Middle Egyptian: An
4
+ Introduction to the Language and Culture of Hieroglyphs][allen].
5
+
6
+ H: π“Šƒπ“€€π“€ | π“Šƒπ“π“ | 𓂋𓏀π“Šͺπ“…±
7
+ L: s | s.t | r-pw
8
+ G: man | woman | whichever
9
+ T: either [a] man or [a] woman
10
+
11
+ You can emphasize an "or" by following the options with {r-pw}.
12
+
13
+ [allen]: http://www.amazon.com/Middle-Egyptian-Introduction-Language-Hieroglyphs/dp/0521741440
Binary file
@@ -0,0 +1,11 @@
1
+ H: 𓃂 | π“ π“ˆ–π“Ώπ“…±π“Š΅π“π“Šͺ | π“Ήπ“ˆ– | π“Ž›π“Œπ“
2
+ L: wab | mnTw-Htp | ir(w)~n | Hnw.t
3
+ G: prΓͺtre | Mentouhotep | nΓ© de | Henout
4
+
5
+ H: 𓃂 | π“‚‹π“ˆ–π“†‘π“‹΄π“ˆ–π“ƒ€π“…± | 𓐙𓉻
6
+ L: wab | rnfsnbw | mAa(-xrw)
7
+ G: prΓͺtre | Renef-senebou | juste de voix
8
+
9
+ H: 𓅭𓏏𓆑 | π“Ž›π“Œπ“ | π“Ήπ“ˆ– | π“‹žπ“ˆ’π“₯𓂝𓂝𓏏 | 𓐙𓉻
10
+ L: sA.t=f | Hnw.t | ir(w) n | nbw(.t)-aat | mAa(.t-xrw)
11
+ G: fille=sa | Henout | nΓ©e de | Neboutaat | juste de voix
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hierogloss/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hierogloss"
8
+ spec.version = Hierogloss::VERSION
9
+ spec.authors = ["Eric Kidd"]
10
+ spec.email = ["git@randomhacks.net"]
11
+ spec.description = %q{Extends the Markdown parser Kramdown to support hieroglyphs, inline multi-column glosses, and output to BBCode for use on forums. Includes an executable for processing files and a webfont version of the Gardiner signs.}
12
+ spec.summary = %q{Markdown extensions for hieroglyphic glosses and BBCode}
13
+ spec.homepage = "https://github.com/emk/hierogloss"
14
+ spec.license = "Public domain + other open source licenses"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "kramdown", "~> 1.3"
22
+ spec.add_development_dependency "prawn", "~> 0.14.0"
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "minitest"
26
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Hierogloss
4
+ #:nodoc: Internal dictionary-related utilities. APIs are not stable.
5
+ module Dictionary
6
+ DATA_DIR = File.join(File.dirname(__FILE__), '..', '..', 'data')
7
+ MDC_MAPPING_PATH = File.join(DATA_DIR, "Unicode-MdC-Mapping-v1.utf8")
8
+
9
+ GARDINER = {}
10
+ File.open(MDC_MAPPING_PATH, "r:bom|utf-8") do |f|
11
+ f.each_line do |l|
12
+ l.chomp!
13
+ sign, hex, codes, remarks = l.split(/\t/, 4)
14
+ for code in codes.split(/ /)
15
+ next unless code =~ /\A[A-Z][0-9]+\z/
16
+ GARDINER[sign] = code
17
+ end
18
+ end
19
+ end
20
+ "𓄿𓇋𓏭𓂝𓅱𓏲𓃀π“Šͺπ“†‘π“…“π“ˆ–π“‚‹π“‰”π“Ž›π“π“„‘π“Šƒπ“‹΄π“ˆ™π“ˆŽπ“Ž‘π“ŽΌπ“π“Ώπ“‚§π“†“".each_char do |c|
21
+ GARDINER.delete(c)
22
+ end
23
+
24
+ # Try to kick things into shape for hierogl.ch.
25
+ def self.headword(word)
26
+ hw = word
27
+ hw.gsub!(/[()]/, '')
28
+ hw.sub!(/=.*\z/, '')
29
+ hw.sub!(/\.w?t\z/, 't')
30
+ hw.sub!(/\..*\z/, '')
31
+ hw
32
+ end
33
+
34
+ # Given a Unicode hieroglyph, get the corresponding Gardiner sign.
35
+ def self.gardiner(sign)
36
+ GARDINER[sign]
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,174 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ require 'hierogloss/dictionary'
5
+
6
+ module Hierogloss
7
+ #:nodoc:
8
+ class Row
9
+ attr_reader :raw_cells
10
+
11
+ def initialize(row_text)
12
+ @raw_cells = row_text.split(/\|/).map {|c| c.strip }
13
+ end
14
+
15
+ def span?
16
+ false
17
+ end
18
+
19
+ def attributes
20
+ attrs = {}
21
+ attrs['class'] = class_attr if class_attr
22
+ attrs
23
+ end
24
+
25
+ def class_attr
26
+ nil
27
+ end
28
+
29
+ def to_kramdown
30
+ attrs = attributes
31
+ tr = Kramdown::Element.new(:tr, nil, attrs)
32
+ raw_cells.each do |c|
33
+ td = Kramdown::Element.new(:td)
34
+ children = cell_to_kramdown(c)
35
+ if children.kind_of?(Array)
36
+ td.children.concat(children)
37
+ else
38
+ td.children << children
39
+ end
40
+ tr.children << td
41
+ end
42
+ tr
43
+ end
44
+
45
+ def cell_to_kramdown(cell)
46
+ Kramdown::Element.new(:text, cell)
47
+ end
48
+
49
+ def search_link(query, text)
50
+ base_url = "http://www.hierogl.ch/hiero/Sp%C3%A9cial:Recherche"
51
+ escaped_query = CGI.escape(query)
52
+ url = "#{base_url}?search=#{escaped_query}&go=Lire"
53
+
54
+ link = Kramdown::Element.new(:a, nil, {'href' => url})
55
+ link.children << Kramdown::Element.new(:text, text)
56
+ link
57
+ end
58
+ end
59
+
60
+ #:nodoc:
61
+ class HieroglyphRow < Row
62
+ def class_attr
63
+ 'hgls-h'
64
+ end
65
+
66
+ def cell_to_kramdown(cell)
67
+ cell.chars.map do |c|
68
+ gardiner = Dictionary.gardiner(c)
69
+ if !gardiner.nil?
70
+ search_link("Signe:#{gardiner}", c)
71
+ else
72
+ Kramdown::Element.new(:text, c)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ #:nodoc:
79
+ class TransliterationRow < Row
80
+ JR_TRANSLITERATION = {
81
+ "A" => "ꜣ",
82
+ "i" => "j",
83
+ "a" => "κœ₯",
84
+ "H" => "αΈ₯",
85
+ "x" => "αΈ«",
86
+ "X" => "αΊ–",
87
+ "S" => "Ε‘",
88
+ "q" => "αΈ³",
89
+ "K" => "αΈ³",
90
+ "T" => "αΉ―",
91
+ "D" => "ḏ"
92
+ }
93
+
94
+ def self.fancy(tl)
95
+ tl.chars.map {|c| JR_TRANSLITERATION[c] || c }.join
96
+ end
97
+
98
+ def class_attr
99
+ 'hgls-l'
100
+ end
101
+
102
+ def cell_to_kramdown(cell)
103
+ fancy = self.class.fancy(cell)
104
+ search_link(Dictionary.headword(cell), fancy)
105
+ end
106
+ end
107
+
108
+ #:nodoc:
109
+ class TranslationRow
110
+ attr_reader :text
111
+
112
+ def initialize(row_text)
113
+ @text = row_text.strip
114
+ end
115
+
116
+ def span?
117
+ true
118
+ end
119
+
120
+ def class_attr
121
+ 'hgls-t'
122
+ end
123
+
124
+ def to_kramdown
125
+ em = Kramdown::Element.new(:em, nil)
126
+ em.children << Kramdown::Element.new(:text, text)
127
+ em
128
+ end
129
+ end
130
+
131
+ #:nodoc:
132
+ class Gloss
133
+ attr_reader :rows
134
+
135
+ def initialize(text)
136
+ @rows = text.lines.map {|l| l.chomp }.map do |row|
137
+ row =~ /\A(\w+):(.*)\z/
138
+ raise "C'est quoi, [[#{row}]]\?" unless $1 && $2
139
+ type =
140
+ case $1
141
+ when "H" then HieroglyphRow
142
+ when "L" then TransliterationRow
143
+ when "T" then TranslationRow
144
+ else Row
145
+ end
146
+ type.new($2)
147
+ end
148
+ end
149
+
150
+ def to_kramdown
151
+ result = []
152
+ # Neither Kramdown nor BBCode support rowspans, so we'll just cheat
153
+ # for now.
154
+ rows.chunk {|r| r.span? }.each do |spans, rows|
155
+ if spans
156
+ rows.each do |r|
157
+ class_attr = "hgls-gloss #{r.class_attr}"
158
+ p = Kramdown::Element.new(:p, nil, 'class' => class_attr)
159
+ p.children << r.to_kramdown
160
+ result << p
161
+ end
162
+ else
163
+ table = Kramdown::Element.new(:table, nil, { 'class' => 'hgls-gloss' },
164
+ alignment: [])
165
+ tbody = Kramdown::Element.new(:tbody)
166
+ table.children << tbody
167
+ rows.each {|r| tbody.children << r.to_kramdown }
168
+ result << table
169
+ end
170
+ end
171
+ result
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,3 @@
1
+ module Hierogloss
2
+ VERSION = "0.0.1"
3
+ end
data/lib/hierogloss.rb ADDED
@@ -0,0 +1,24 @@
1
+ require 'kramdown'
2
+ require "hierogloss/version"
3
+ require "hierogloss/dictionary"
4
+ require "hierogloss/gloss"
5
+ require "kramdown/parser/hierogloss"
6
+ require "kramdown/converter/bbcode"
7
+ # No guarantess of backwards compatibility for this one.
8
+ require "kramdown/converter/htlal"
9
+
10
+ # Most of our internal APIs are undocumented at this point, but you
11
+ # can use this gem via Kramdown's APIs.
12
+ #
13
+ # Kramdown::Document.new(ARGF.read, input: 'hierogloss').to_html
14
+ #
15
+ # Or if you want to post on an online forum, try:
16
+ #
17
+ # Kramdown::Document.new(ARGF.read, input: 'hierogloss').to_bbcode
18
+ #
19
+ # Note that the BBCode converter does not yet support all available
20
+ # Markdown constructs. You're welcome to try other kramdown backends;
21
+ # some of them may more-or-less work.
22
+ module Hierogloss
23
+ # Nothing to do here yet.
24
+ end
@@ -0,0 +1,113 @@
1
+ module Kramdown
2
+ module Converter
3
+ # Outputs some of the most common Markdown elements as BBCode.
4
+ # Everything in this class is internal.
5
+ class Bbcode < Base
6
+ include ::Kramdown::Utils::Html
7
+
8
+ DISPATCHER = Hash.new {|h,k| h[k] = "convert_#{k}"} #:nodoc:
9
+
10
+ def initialize(root, options)
11
+ super
12
+ @stack = []
13
+ end
14
+
15
+ def convert(el, opts = {})
16
+ send(DISPATCHER[el.type], el, opts)
17
+ end
18
+
19
+ def inner(el, opts)
20
+ @stack.push([el, opts])
21
+ result = el.children.map do |inner_el|
22
+ convert(inner_el, options)
23
+ end
24
+ @stack.pop
25
+ result
26
+ end
27
+
28
+ def convert_header(el, opts)
29
+ tag("b", nil, inner(el, opts)) + ["\n"]
30
+ end
31
+
32
+ def convert_p(el, opts)
33
+ inner(el, opts) + ["\n"]
34
+ end
35
+
36
+ def convert_blank(el, opts)
37
+ "\n"
38
+ end
39
+
40
+ def convert_text(el, opts)
41
+ # Wouldn't it be nice if we could escape BBCode?
42
+ el.value.gsub(/\s+/, ' ') # Ignore newlines in raw text.
43
+ end
44
+
45
+ def convert_em(el, opts)
46
+ tag("i", nil, inner(el, opts))
47
+ end
48
+
49
+ def convert_strong(el, opts)
50
+ tag("b", nil, inner(el, opts))
51
+ end
52
+
53
+ def convert_a(el, opts)
54
+ tag("url", el.attr['href'], inner(el, opts))
55
+ end
56
+
57
+ def convert_smart_quote(el, opts)
58
+ entity_to_str(smart_quote_entity(el))
59
+ end
60
+
61
+ def convert_table(el, opts)
62
+ tag("table", nil, ["\n"] + inner(el, opts))
63
+ end
64
+
65
+ def convert_tbody(el, opts)
66
+ inner(el, opts)
67
+ end
68
+
69
+ def convert_tr(el, opts)
70
+ tag("tr", nil, inner(el, opts)) + ["\n"]
71
+ end
72
+
73
+ def convert_td(el, opts)
74
+ if @stack.last.first.attr['class'] == 'hgls-h'
75
+ tag("td", nil, tag("size", "24", inner(el, opts)))
76
+ else
77
+ tag("td", nil, inner(el, opts))
78
+ end
79
+ end
80
+
81
+ def convert_blockquote(el, opts)
82
+ # No newline because BBCode will add one itself. We also run
83
+ # results_to_text so we can clean up trailing newlines.
84
+ tag("quote", nil, results_to_text(inner(el, opts)))
85
+ end
86
+
87
+ def convert_codeblock(el, opts)
88
+ # No newline because BBCode will add one itself.
89
+ tag("code", nil, el.value.sub(/\n\z/, ''))
90
+ end
91
+
92
+ def convert_img(el, opts)
93
+ tag("img", nil, el.attr['src'])
94
+ end
95
+
96
+ def convert_root(el, opts)
97
+ results_to_text(inner(el, opts))
98
+ end
99
+
100
+ def tag(name, arg, content)
101
+ if arg
102
+ ["[#{name}=#{arg}]", content, "[/#{name}]"]
103
+ else
104
+ ["[#{name}]", content, "[/#{name}]"]
105
+ end
106
+ end
107
+
108
+ def results_to_text(results)
109
+ results.flatten.compact.join.sub(/\n+\z/, '')
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,34 @@
1
+ module Kramdown
2
+ module Converter
3
+ # Outputs some of the most common Markdown elements in a stripped down
4
+ # BBCode dialect without table support or reliable font size control.
5
+ # Everything in this class is internal.
6
+ class Htlal < Bbcode
7
+ include ::Kramdown::Utils::Html
8
+
9
+ def convert_table(el, opts)
10
+ inner(el, opts)
11
+ end
12
+
13
+ def convert_tbody(el, opts)
14
+ inner(el, opts)
15
+ end
16
+
17
+ def convert_tr(el, opts)
18
+ spaced = []
19
+ inner(el, opts).each do |td|
20
+ spaced << td << " | "
21
+ end
22
+ spaced.pop
23
+ spaced << "\n"
24
+ spaced
25
+ end
26
+
27
+ def convert_td(el, opts)
28
+ # We'd like to make hieroglyph cells bigger, but that doesn't play
29
+ # nicely with links.
30
+ inner(el, opts)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ module Kramdown
2
+ module Parser
3
+ # Parses an extended Kramdown syntax with support for inline glosses.
4
+ # Everything in this class is internal.
5
+ class Hierogloss < ::Kramdown::Parser::Kramdown
6
+ def initialize(source, options)
7
+ super
8
+ @span_parsers.unshift(:translit)
9
+ @block_parsers.unshift(:gloss)
10
+ end
11
+
12
+ TRANSLIT_START = /{.*?}/
13
+
14
+ def parse_translit
15
+ @src.pos += @src.matched_size
16
+ mdc = @src.matched[1..-2]
17
+ em = Element.new(:em, nil, 'class' => 'hgls-l')
18
+ em.children <<
19
+ Element.new(:text, ::Hierogloss::TransliterationRow.fancy(mdc))
20
+ @tree.children << em
21
+ end
22
+ define_parser(:translit, TRANSLIT_START, '{')
23
+
24
+ GLOSS_START = /^(H|L|G|T):/
25
+ GLOSS_MATCH = /((^(H|L|G|T):.*)\r?\n)*/
26
+
27
+ def parse_gloss
28
+ start_line_number = @src.current_line_number
29
+ data = @src.scan(self.class::GLOSS_MATCH)
30
+ @tree.children.concat(::Hierogloss::Gloss.new(data).to_kramdown)
31
+ true
32
+ end
33
+
34
+ define_parser(:gloss, GLOSS_START)
35
+ end
36
+ end
37
+ end
data/src/Gardiner.ttf ADDED
Binary file
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'hierogloss'
3
+
4
+ require 'minitest/autorun'
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'minitest_helper'
3
+
4
+ class TestDictionary < Minitest::Test
5
+ def assert_hw(headword, word)
6
+ assert_equal(headword, Hierogloss::Dictionary.headword(word))
7
+ end
8
+
9
+ def test_should_leave_simple_headwords_alone
10
+ assert_hw("xr", "xr")
11
+ assert_hw("Hr", "Hr")
12
+ end
13
+
14
+ def test_should_strip_parens
15
+ assert_hw("ny", "n(y)")
16
+ assert_hw("mAa-Hrw", "mAa(-Hrw)")
17
+ end
18
+
19
+ def test_should_strip_clitics
20
+ assert_hw("ir", "ir=n")
21
+ assert_hw("im", "im=s")
22
+ end
23
+
24
+ def test_should_remove_dot_before_t
25
+ assert_hw("Sspt", "Ssp.t")
26
+ assert_hw("Hmt", "Hm.t")
27
+ end
28
+
29
+ def test_should_strip_plurals
30
+ assert_hw("Sspt", "Ssp.wt")
31
+ assert_hw("hrw", "hrw.w")
32
+ end
33
+
34
+ def test_should_strip_verb_endings
35
+ assert_hw("ir", "ir.n=f")
36
+ assert_hw("Dd", "Dd.n")
37
+ end
38
+
39
+ def test_should_provide_gardiner_signs_for_most_signs
40
+ assert_equal("A1", Hierogloss::Dictionary.gardiner("π“€€"))
41
+ assert_equal("D4", Hierogloss::Dictionary.gardiner("𓁹"))
42
+ end
43
+
44
+ def test_should_not_provide_gardiner_signs_for_uniliterals
45
+ # Let's not link these common characters.
46
+ "𓄿𓇋𓏭𓂝𓅱𓏲𓃀π“Šͺπ“†‘π“…“π“ˆ–π“‚‹π“‰”π“Ž›π“π“„‘π“Šƒπ“‹΄π“ˆ™π“ˆŽπ“Ž‘π“ŽΌπ“π“Ώπ“‚§π“†“".each_char do |c|
47
+ assert_nil(Hierogloss::Dictionary.gardiner(c), "should not translate #{c}")
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'minitest_helper'
3
+
4
+ class TestGloss < MiniTest::Test
5
+ include Hierogloss
6
+
7
+ def setup
8
+ input = <<EOD
9
+ H: π“Šƒπ“€€π“€ | π“Šƒπ“π“
10
+ L: s | s.t
11
+ G: homme | femme
12
+ T: l'homme et la femme
13
+ EOD
14
+ @gloss = Hierogloss::Gloss.new(input)
15
+ end
16
+
17
+ def assert_row(type, raw_cells, row)
18
+ assert_instance_of(type, row)
19
+ refute(row.span?)
20
+ assert_equal(raw_cells, row.raw_cells)
21
+ end
22
+
23
+ def test_should_parse_gloss_into_appropriate_rows
24
+ assert_equal(4, @gloss.rows.length)
25
+ assert_row(HieroglyphRow, ["π“Šƒπ“€€π“€", "π“Šƒπ“π“"], @gloss.rows[0])
26
+ assert_row(TransliterationRow, ["s", "s.t"], @gloss.rows[1])
27
+ assert_row(Row, ["homme", "femme"], @gloss.rows[2])
28
+
29
+ # Translations don't have cells.
30
+ assert_instance_of(TranslationRow, @gloss.rows[3])
31
+ assert(@gloss.rows[3].span?)
32
+ assert_equal("l'homme et la femme", @gloss.rows[3].text)
33
+ end
34
+
35
+ def test_should_be_convertible_to_a_list_of_kramdown_elements
36
+ # We don't actually care what's in there; we just want to render
37
+ # something plausible.
38
+ kramdown = @gloss.to_kramdown
39
+ assert_instance_of(Array, kramdown)
40
+ assert(kramdown.length > 0)
41
+ kramdown.each {|k| assert_instance_of(Kramdown::Element, k) }
42
+ end
43
+ end
@@ -0,0 +1,7 @@
1
+ require 'minitest_helper'
2
+
3
+ class TestHierogloss < MiniTest::Test
4
+ def test_that_it_has_a_version_number
5
+ refute_nil ::Hierogloss::VERSION
6
+ end
7
+ end