nora_mark 0.2beta3
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 +7 -0
- data/.gitignore +19 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +188 -0
- data/Rakefile +12 -0
- data/lib/nora_mark/html/abstract_item_writer.rb +14 -0
- data/lib/nora_mark/html/context.rb +119 -0
- data/lib/nora_mark/html/generator.rb +177 -0
- data/lib/nora_mark/html/header_writer.rb +35 -0
- data/lib/nora_mark/html/pages.rb +56 -0
- data/lib/nora_mark/html/paragraph_writer.rb +52 -0
- data/lib/nora_mark/html/tag_writer.rb +110 -0
- data/lib/nora_mark/html/util.rb +12 -0
- data/lib/nora_mark/html/writer_selector.rb +24 -0
- data/lib/nora_mark/parser.kpeg +123 -0
- data/lib/nora_mark/parser.kpeg.rb +3422 -0
- data/lib/nora_mark/parser.rb +31 -0
- data/lib/nora_mark/version.rb +3 -0
- data/lib/nora_mark.rb +46 -0
- data/nora_mark.gemspec +22 -0
- data/spec/created_files/.gitignore +1 -0
- data/spec/fixture/test_src_ja.nora +50 -0
- data/spec/nokogiri_test_helper.rb +41 -0
- data/spec/nora_mark_spec.rb +840 -0
- data/spec/spec_helper.rb +29 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8a2886da05fdf6ceef15ef567fe80634a580b381
|
4
|
+
data.tar.gz: 0a34c663272a064a68d6256f1743008309fcf0ca
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a38237dbfa6e03d97caf7b80c00413b968faf1e1efb731b692212dee2c33a3dfedc769108dc4ad2c7ef70349ed32afd5d3d69ba9ee69ef3b712f91862fd52d97
|
7
|
+
data.tar.gz: 3cc67438a689ecfaf3ef11e635ee8d09c9d0b8f8ff50ecfbbd61ccfc7cc973081e1a313d921460fcfaf66bde4216467e2de381b2f41b525fa630427f8e60a22b
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# version 0.2beta1 (NoraMark beta)
|
2
|
+
* Change name to NoraMark
|
3
|
+
|
4
|
+
# version 0.1beta3 (pre NoraMark)
|
5
|
+
|
6
|
+
* Totally rewrite using kpeg.
|
7
|
+
* remove toc feature (for the old toc feature is so poor)
|
8
|
+
* removed custom BlockParser. Instead of the feature, easy and powerful customization will be introduced in NoraText 0.2
|
9
|
+
* markup change: alternate block notation stnorang with 'd{---' has removed
|
10
|
+
* markup change: inline image notation is changed form [img(alt-text){src}] to [img(src, alt)]
|
11
|
+
|
12
|
+
|
13
|
+
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 KOJIMA Satoshi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
# NoraMark
|
2
|
+
|
3
|
+
NoraMark is a simple text markup language. It is designed to create XHTML files for EPUB books. Its default mode is for Japanese text.
|
4
|
+
|
5
|
+
**CAUTION This is very early alpha version, so it's not stable at all, even the markup syntax**
|
6
|
+
|
7
|
+
In the next release, the library name will change from NoraMark to NoraMark.
|
8
|
+
In NoraMark release version, the syntax will be more stable.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'nora_mark'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install nora_mark
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
require 'nora_mark'
|
27
|
+
|
28
|
+
document = NoraMark::Document.parse(string_or_io)
|
29
|
+
put document.html[0] # outputs 1st page of converted XHTML file
|
30
|
+
|
31
|
+
An example of markup text (text is in english, but the paragraph style is japanese)
|
32
|
+
|
33
|
+
# line begins with # is a comment.
|
34
|
+
# you don't need to indent noramark text.
|
35
|
+
|
36
|
+
lang: ja
|
37
|
+
title: test title
|
38
|
+
stylesheets: css/normalize.css, css/main.css
|
39
|
+
|
40
|
+
art {
|
41
|
+
h1: header 1
|
42
|
+
article comes here.
|
43
|
+
linebreak will produce paragraph.
|
44
|
+
|
45
|
+
blank line will procude div.pgroup.
|
46
|
+
|
47
|
+
d.column {
|
48
|
+
This block will produce div.column.
|
49
|
+
Inline commands like [link(http://github.com/skoji/nora_mark/){this}] and [s.strong{this}] is available.
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
The converted XHTML file
|
54
|
+
|
55
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
56
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
57
|
+
<head>
|
58
|
+
<title> test title</title>
|
59
|
+
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
|
60
|
+
<link rel="stylesheet" type="text/css" href="css/main.css" />
|
61
|
+
</head>
|
62
|
+
<body>
|
63
|
+
<article>
|
64
|
+
<h1>header 1</h1>
|
65
|
+
<div class='pgroup'>
|
66
|
+
<p>article comes here.</p>
|
67
|
+
<p>linebreak will produce paragraph.</p>
|
68
|
+
</div>
|
69
|
+
<div class='pgroup'>
|
70
|
+
<p>blank line will produce</p>
|
71
|
+
</div>
|
72
|
+
<div class='column'>
|
73
|
+
<div class='pgroup'>
|
74
|
+
<p>This block will produce div.column.</p>
|
75
|
+
<p>Inline commands like <a href='http://github.com/skoji/nora_mark/'>this</a> and <span class='strong'>this</span> is available.</p>
|
76
|
+
</div>
|
77
|
+
</div>
|
78
|
+
</article>
|
79
|
+
</body>
|
80
|
+
</html>
|
81
|
+
|
82
|
+
Another example of markup text in non-japanese (paragraph style is default)
|
83
|
+
|
84
|
+
# line begins with # is a comment.
|
85
|
+
# you don't need to indent noramark text.
|
86
|
+
|
87
|
+
lang: en
|
88
|
+
title: test title
|
89
|
+
stylesheets: css/normalize.css, css/main.css
|
90
|
+
|
91
|
+
art {
|
92
|
+
h1: header 1
|
93
|
+
article comes here.
|
94
|
+
linebreak will produce br.
|
95
|
+
|
96
|
+
blank line will procude paragraph.
|
97
|
+
|
98
|
+
d.column {
|
99
|
+
This block will produce div.column.
|
100
|
+
Inline commands like [link(http://github.com/skoji/nora_mark/){this}] and [s.strong{this}] is available.
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
The converted XHTML file
|
105
|
+
|
106
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
107
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
108
|
+
<head>
|
109
|
+
<title> test title</title>
|
110
|
+
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
|
111
|
+
<link rel="stylesheet" type="text/css" href="css/main.css" />
|
112
|
+
</head>
|
113
|
+
<body>
|
114
|
+
<article>
|
115
|
+
<h1>header 1</h1>
|
116
|
+
<p>article comes here.<br />linebreak will produce paragraph.</p>
|
117
|
+
<p>blank line will produce paragraph</p>
|
118
|
+
<div class='column'>
|
119
|
+
<p>This block will produce div.column.<br />Inline commands like <a href='http://github.com/skoji/nora_mark/'>this</a> and <span class='strong'>this</span> is available.</p>
|
120
|
+
</div>
|
121
|
+
</article>
|
122
|
+
</body>
|
123
|
+
</html>
|
124
|
+
|
125
|
+
|
126
|
+
Another example of markup text
|
127
|
+
|
128
|
+
# Markdown-ish heading will creates section
|
129
|
+
|
130
|
+
lang: ja
|
131
|
+
title: test title
|
132
|
+
stylesheets: css/normalize.css, css/main.css
|
133
|
+
|
134
|
+
=: this is the first heading
|
135
|
+
|
136
|
+
This line is in a section.
|
137
|
+
This line is in a section.
|
138
|
+
|
139
|
+
==: this is the second heading
|
140
|
+
|
141
|
+
This section is nested.
|
142
|
+
|
143
|
+
=: this is the third heading
|
144
|
+
|
145
|
+
will terminate lower level section
|
146
|
+
|
147
|
+
The converted XHTML file
|
148
|
+
|
149
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
150
|
+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
|
151
|
+
<head>
|
152
|
+
<title>test title</title>
|
153
|
+
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
|
154
|
+
<link rel="stylesheet" type="text/css" href="css/main.css" />
|
155
|
+
</head>
|
156
|
+
<body>
|
157
|
+
<section><h1>this is the first heading</h1>
|
158
|
+
<div class='pgroup'><p>This line is in a section.</p>
|
159
|
+
<p>This line is in a section.</p>
|
160
|
+
</div>
|
161
|
+
<section><h2>this is the second heading</h2>
|
162
|
+
<div class='pgroup'><p>This section is nested.</p>
|
163
|
+
</div>
|
164
|
+
</section>
|
165
|
+
</section>
|
166
|
+
<section><h1>this is the third heading</h1>
|
167
|
+
<div class='pgroup'><p>will terminate lower level section</p>
|
168
|
+
</div>
|
169
|
+
</section>
|
170
|
+
</body>
|
171
|
+
</html>
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
|
180
|
+
In a near future version, you will be able to add custom commands.
|
181
|
+
|
182
|
+
## Contributing
|
183
|
+
|
184
|
+
1. Fork it
|
185
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
186
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
187
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
188
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
rule(/\.kpeg\.rb/ => proc {|task_name| task_name.sub(/kpeg\.rb$/, 'kpeg')}) do
|
5
|
+
|t|
|
6
|
+
system "kpeg -f #{t.prerequisites[0]}"
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "run rspec"
|
10
|
+
task :test => ["lib/nora_mark/parser.kpeg.rb"] do
|
11
|
+
system 'rspec'
|
12
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module NoraMark
|
2
|
+
module Html
|
3
|
+
class Context
|
4
|
+
attr_accessor :title, :head_inserters, :toc, :lang, :stylesheets, :enable_pgroup
|
5
|
+
def initialize(param = {})
|
6
|
+
@head_inserters = []
|
7
|
+
@toc = []
|
8
|
+
@lang = param[:lang] || 'en'
|
9
|
+
@title = param[:title] || 'NoraMark generated document'
|
10
|
+
@stylesheets = param[:stylesheets] || []
|
11
|
+
@stylesheets_alt = param[:stylesheets_alt] || []
|
12
|
+
@enable_pgroup = param[:enable_pgroup] || true
|
13
|
+
self.paragraph_style= param[:paragraph_style]
|
14
|
+
@pages = Pages.new(param[:filename_base], param[:sequence_format])
|
15
|
+
@block_delimiter_stack = []
|
16
|
+
head_inserter do
|
17
|
+
ret = ""
|
18
|
+
@stylesheets.each { |s|
|
19
|
+
if s.is_a? String
|
20
|
+
ret << "<link rel=\"stylesheet\" type=\"text/css\" href=\"#{s}\" />\n"
|
21
|
+
elsif s.is_a? Array
|
22
|
+
ret << "<link rel=\"stylesheet\" type=\"text/css\" media=\"#{s[1]}\" href=\"#{s[0]}\" />\n"
|
23
|
+
else
|
24
|
+
raise "Can't use #{s} as a stylesheet"
|
25
|
+
end
|
26
|
+
}
|
27
|
+
ret
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def created_files
|
32
|
+
@pages.created_files
|
33
|
+
end
|
34
|
+
|
35
|
+
def chop_last_space
|
36
|
+
@pages.last.sub!(/[[:space:]]+$/, '')
|
37
|
+
end
|
38
|
+
|
39
|
+
def paragraph_style=(style)
|
40
|
+
return if style.nil?
|
41
|
+
raise "paragrapy_style accepts only :default or :use_paragraph_group but is #{style}" if style != :default && style != :use_paragraph_group
|
42
|
+
@paragraph_style = style
|
43
|
+
end
|
44
|
+
|
45
|
+
def paragraph_style
|
46
|
+
if @paragraph_style
|
47
|
+
@paragraph_style
|
48
|
+
elsif @lang.split('-')[0] == 'ja'
|
49
|
+
:use_paragraph_group
|
50
|
+
else
|
51
|
+
:default
|
52
|
+
end
|
53
|
+
end
|
54
|
+
def head_inserter(&block)
|
55
|
+
head_inserters << block
|
56
|
+
end
|
57
|
+
|
58
|
+
def start_html(title = nil)
|
59
|
+
@title = title if !title.nil?
|
60
|
+
if @pages.size >0 && !@pages.last.frozen?
|
61
|
+
end_html
|
62
|
+
end
|
63
|
+
page = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
64
|
+
page << "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"#{@lang}\" xml:lang=\"#{@lang}\">\n"
|
65
|
+
page << "<head>\n"
|
66
|
+
page << "<title>#{@title}</title>\n"
|
67
|
+
@head_inserters.each {
|
68
|
+
|f|
|
69
|
+
page << f.call
|
70
|
+
}
|
71
|
+
page << "</head>\n"
|
72
|
+
page << "<body>\n"
|
73
|
+
@pages << page
|
74
|
+
@toc << title
|
75
|
+
end
|
76
|
+
|
77
|
+
def end_html
|
78
|
+
page = @pages.last
|
79
|
+
if !page.frozen?
|
80
|
+
page << "</body>\n"
|
81
|
+
page << "</html>\n"
|
82
|
+
page.freeze
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def enter_block(lexed)
|
87
|
+
@block_delimiter_stack.push(lexed[:delimiter])
|
88
|
+
end
|
89
|
+
|
90
|
+
def exit_block(lexed)
|
91
|
+
@block_delimiter_stack.pop
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def block_close?(line)
|
96
|
+
line == (@block_delimiter_stack.last || '') + '}'
|
97
|
+
end
|
98
|
+
|
99
|
+
def toc=(label)
|
100
|
+
@toc[-1] = label if @toc.size > 0
|
101
|
+
end
|
102
|
+
|
103
|
+
def <<(text)
|
104
|
+
if @pages.size == 0 || @pages.last.frozen?
|
105
|
+
start_html
|
106
|
+
end
|
107
|
+
@pages.last << text
|
108
|
+
end
|
109
|
+
|
110
|
+
def result
|
111
|
+
if !@pages.last.frozen?
|
112
|
+
end_html
|
113
|
+
end
|
114
|
+
|
115
|
+
@pages
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'nora_mark/html/util'
|
3
|
+
require 'nora_mark/html/pages'
|
4
|
+
require 'nora_mark/html/context'
|
5
|
+
require 'nora_mark/html/tag_writer'
|
6
|
+
require 'nora_mark/html/header_writer'
|
7
|
+
require 'nora_mark/html/paragraph_writer'
|
8
|
+
require 'nora_mark/html/writer_selector'
|
9
|
+
require 'nora_mark/html/abstract_item_writer'
|
10
|
+
module NoraMark
|
11
|
+
module Html
|
12
|
+
class Generator
|
13
|
+
include Util
|
14
|
+
attr_reader :context
|
15
|
+
def initialize(param = {})
|
16
|
+
@context = Context.new(param)
|
17
|
+
article_writer = TagWriter.create('article', self)
|
18
|
+
section_writer = TagWriter.create('section', self)
|
19
|
+
link_writer = TagWriter.create('a', self, trailer: '',
|
20
|
+
item_preprocessor: proc do |item|
|
21
|
+
(item[:attrs] ||= {}).merge!({:href => [ item[:args][0] ]})
|
22
|
+
item
|
23
|
+
end)
|
24
|
+
|
25
|
+
header_writer = HeaderWriter.new self
|
26
|
+
paragraph_writer = ParagraphWriter.new self
|
27
|
+
abstract_item_writer = AbstractItemWriter.new self
|
28
|
+
@writers = {
|
29
|
+
:page => abstract_item_writer,
|
30
|
+
:headers => abstract_item_writer,
|
31
|
+
:paragraph => paragraph_writer,
|
32
|
+
:paragraph_group => paragraph_writer,
|
33
|
+
:block =>
|
34
|
+
WriterSelector.new(self,
|
35
|
+
{
|
36
|
+
'd' => TagWriter.create('div', self),
|
37
|
+
'art' => article_writer,
|
38
|
+
'arti' => article_writer,
|
39
|
+
'article' => article_writer,
|
40
|
+
'sec' => section_writer,
|
41
|
+
'sect' => section_writer,
|
42
|
+
'section' => section_writer,
|
43
|
+
}),
|
44
|
+
:line_command =>
|
45
|
+
WriterSelector.new(self,
|
46
|
+
{
|
47
|
+
'image' =>
|
48
|
+
TagWriter.create('div', self,
|
49
|
+
item_preprocessor: proc do |item|
|
50
|
+
add_class_if_empty item, 'img-wrap'
|
51
|
+
item
|
52
|
+
end,
|
53
|
+
write_body_preprocessor: proc do |item|
|
54
|
+
src = item[:args][0].strip
|
55
|
+
alt = (item[:args][1] || '').strip
|
56
|
+
caption_before = item[:named_args][:caption_before]
|
57
|
+
if caption_before && children_not_empty(item)
|
58
|
+
output "<p>"; write_children item; output "</p>"
|
59
|
+
end
|
60
|
+
output "<img src='#{src}' alt='#{escape_html alt}' />"
|
61
|
+
if !caption_before && children_not_empty(item)
|
62
|
+
output "<p>"; write_children item; output "</p>"
|
63
|
+
end
|
64
|
+
:done
|
65
|
+
end
|
66
|
+
),
|
67
|
+
|
68
|
+
}),
|
69
|
+
:inline =>
|
70
|
+
WriterSelector.new(self,
|
71
|
+
{
|
72
|
+
'link' => link_writer,
|
73
|
+
'l' => link_writer,
|
74
|
+
's' => TagWriter.create('span', self),
|
75
|
+
'img' =>
|
76
|
+
TagWriter.create('img', self,
|
77
|
+
item_preprocessor: proc do |item|
|
78
|
+
item[:no_body] = true #TODO : it is not just an item's attribute, 'img_inline' has no body. maybe should specify in parser.{rb|kpeg}
|
79
|
+
(item[:attrs] ||= {}).merge!({:src => [item[:args][0] ]})
|
80
|
+
item[:attrs].merge!({:alt => [ escape_html(item[:args][1].strip)]}) if (item[:args].size > 1 && item[:args][1].size > 0)
|
81
|
+
item
|
82
|
+
end) ,
|
83
|
+
'tcy' =>
|
84
|
+
TagWriter.create('span', self,
|
85
|
+
item_preprocessor: proc do |item|
|
86
|
+
add_class item, 'tcy'
|
87
|
+
item
|
88
|
+
end),
|
89
|
+
'ruby' =>
|
90
|
+
TagWriter.create('ruby', self,
|
91
|
+
write_body_preprocessor: proc do |item|
|
92
|
+
write_children item
|
93
|
+
output "<rp>(</rp><rt>#{escape_html item[:args][0].strip}</rt><rp>)</rp>"
|
94
|
+
:done
|
95
|
+
end),
|
96
|
+
|
97
|
+
},
|
98
|
+
trailer_default:''
|
99
|
+
),
|
100
|
+
:ol => TagWriter.create('ol', self),
|
101
|
+
:ul => TagWriter.create('ul', self),
|
102
|
+
:li => TagWriter.create('li', self),
|
103
|
+
:dl => TagWriter.create('dl', self),
|
104
|
+
:dtdd =>
|
105
|
+
TagWriter.create('', self, chop_last_space: true, item_preprocessor: proc do |item| item[:no_tag] = true; item end,
|
106
|
+
write_body_preprocessor: proc do |item|
|
107
|
+
output "<dt>"; write_array item[:args][0]; output "</dt>"
|
108
|
+
output "<dd>"; write_array item[:args][1]; output "</dd>"
|
109
|
+
:done
|
110
|
+
end),
|
111
|
+
:newpage =>
|
112
|
+
TagWriter.create('div', self,
|
113
|
+
item_preprocessor: proc do |item|
|
114
|
+
item[:no_tag] = true
|
115
|
+
item
|
116
|
+
end,
|
117
|
+
write_body_preprocessor: proc do |item|
|
118
|
+
title = nil
|
119
|
+
if item[:args].size > 0 && item[:args][0].size > 0
|
120
|
+
title = escape_html item[:args].first
|
121
|
+
end
|
122
|
+
@context.title = title unless title.nil?
|
123
|
+
@context.end_html
|
124
|
+
:done
|
125
|
+
end
|
126
|
+
),
|
127
|
+
#headed-section
|
128
|
+
:h_section =>
|
129
|
+
TagWriter.create('section', self, write_body_preprocessor: proc do |item|
|
130
|
+
output "<h#{item[:level]}>#{item[:heading].strip}</h#{item[:level]}>\n"
|
131
|
+
:continue
|
132
|
+
end),
|
133
|
+
# headers
|
134
|
+
:stylesheets => header_writer,
|
135
|
+
:title => header_writer,
|
136
|
+
:lang => header_writer,
|
137
|
+
:paragraph_style => header_writer,
|
138
|
+
# pre-formatted
|
139
|
+
:preformatted =>
|
140
|
+
TagWriter.create('pre', self,write_body_preprocessor: proc do |item|
|
141
|
+
output "<code>" if item[:name] == 'precode'
|
142
|
+
output item[:children].join "\n"
|
143
|
+
output "</code>" if item[:name] == 'precode'
|
144
|
+
:done
|
145
|
+
end),
|
146
|
+
#break
|
147
|
+
:br =>
|
148
|
+
TagWriter.create('br', self, item_preprocessor: proc do |item|
|
149
|
+
item[:no_body] = true
|
150
|
+
item
|
151
|
+
end),
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
def convert(parsed_result)
|
156
|
+
parsed_result.each {
|
157
|
+
|item|
|
158
|
+
to_html(item)
|
159
|
+
}
|
160
|
+
@context.result
|
161
|
+
end
|
162
|
+
def to_html(item)
|
163
|
+
if item.is_a? String
|
164
|
+
@context << escape_html(item)
|
165
|
+
else
|
166
|
+
writer = @writers[item[:type]]
|
167
|
+
if writer.nil?
|
168
|
+
warn "can't find html generator for \"#{item}\""
|
169
|
+
@context << escape_html(item[:raw_text])
|
170
|
+
else
|
171
|
+
writer.write(item)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module NoraMark
|
2
|
+
module Html
|
3
|
+
class HeaderWriter
|
4
|
+
include Util
|
5
|
+
def initialize(generator)
|
6
|
+
@generator = generator
|
7
|
+
@context = generator.context
|
8
|
+
@writers = {
|
9
|
+
:stylesheets => proc do |item|
|
10
|
+
@context.stylesheets.concat( item[:stylesheets].map do
|
11
|
+
|s|
|
12
|
+
if s =~ /^(.+?\.css):\((.+?)\)$/
|
13
|
+
[$1, $2]
|
14
|
+
else
|
15
|
+
s
|
16
|
+
end
|
17
|
+
end)
|
18
|
+
end,
|
19
|
+
:title => proc do |item|
|
20
|
+
@context.title = escape_html item[:title].strip
|
21
|
+
end,
|
22
|
+
:lang => proc do |item|
|
23
|
+
@context.lang = escape_html item[:lang].strip
|
24
|
+
end,
|
25
|
+
:paragraph_style => proc do |item|
|
26
|
+
@context.paragraph_style = item[:paragraph_style].strip
|
27
|
+
end
|
28
|
+
}
|
29
|
+
end
|
30
|
+
def write(item)
|
31
|
+
@writers[item[:type]].call item
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
module NoraMark
|
3
|
+
module Html
|
4
|
+
class Context
|
5
|
+
class Pages
|
6
|
+
attr_reader :created_files
|
7
|
+
def initialize(filename_base = nil, sequence_format='%05d')
|
8
|
+
@filename_base = filename_base || "noramark_#{SecureRandom.uuid}"
|
9
|
+
@sequence_format = sequence_format || '%05d'
|
10
|
+
@result = []
|
11
|
+
end
|
12
|
+
|
13
|
+
def last
|
14
|
+
@result.last[:content]
|
15
|
+
end
|
16
|
+
|
17
|
+
def size
|
18
|
+
@result.size
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<(page)
|
22
|
+
seq = @result.size + 1
|
23
|
+
@result << { content: page, filename: "#{@filename_base}_#{@sequence_format%(seq)}.xhtml" }
|
24
|
+
end
|
25
|
+
|
26
|
+
def [](num)
|
27
|
+
page = @result[num]
|
28
|
+
page.nil? ? nil : page[:content]
|
29
|
+
end
|
30
|
+
|
31
|
+
def pages
|
32
|
+
@result
|
33
|
+
end
|
34
|
+
|
35
|
+
def write_as_files(directory: nil)
|
36
|
+
dir = directory || Dir.pwd
|
37
|
+
Dir.chdir(dir) do
|
38
|
+
@result.each do
|
39
|
+
|page|
|
40
|
+
File.open(page[:filename], 'w+') do
|
41
|
+
|file|
|
42
|
+
file << page[:content]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def write_as_single_file(filename)
|
48
|
+
File.open(filename, 'w+') {
|
49
|
+
|file|
|
50
|
+
file << @result[0][:content]
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|