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
@@ -0,0 +1,52 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
module NoraMark
|
3
|
+
module Html
|
4
|
+
class ParagraphWriter
|
5
|
+
def initialize(generator)
|
6
|
+
@generator = generator
|
7
|
+
@context = generator.context
|
8
|
+
@writer_set = { use_paragraph_group: {
|
9
|
+
:paragraph =>
|
10
|
+
TagWriter.create('p', @generator, chop_last_space: true,
|
11
|
+
item_preprocessor: proc do |item|
|
12
|
+
add_class(item, 'noindent') if item[:children][0] =~/^(「|『|()/ # TODO: should be plaggable}
|
13
|
+
item
|
14
|
+
end
|
15
|
+
),
|
16
|
+
:paragraph_group =>
|
17
|
+
TagWriter.create("div", @generator,
|
18
|
+
item_preprocessor: proc do |item|
|
19
|
+
add_class item, 'pgroup'
|
20
|
+
item[:no_tag] = true unless @context.enable_pgroup
|
21
|
+
item
|
22
|
+
end
|
23
|
+
)
|
24
|
+
},
|
25
|
+
default: {
|
26
|
+
:paragraph =>
|
27
|
+
TagWriter.create(nil, @generator, chop_last_space: true,
|
28
|
+
item_preprocessor: proc do |item|
|
29
|
+
item[:no_tag] = true
|
30
|
+
item
|
31
|
+
end),
|
32
|
+
:paragraph_group =>
|
33
|
+
TagWriter.create("p", @generator,
|
34
|
+
item_preprocessor: proc do |item|
|
35
|
+
item[:children] = item[:children].inject([]) do |memo, item|
|
36
|
+
memo << { :type => :br, :args => [] } if !memo.last.nil? && memo.last[:type] == :paragraph && item[:type] == :paragraph
|
37
|
+
memo << item
|
38
|
+
end
|
39
|
+
item
|
40
|
+
end
|
41
|
+
)
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
def write(item)
|
46
|
+
writer_set = @writer_set[@context.paragraph_style]
|
47
|
+
writer_set = @writer_set['default'] if writer_set.nil?
|
48
|
+
writer_set[item[:type]].write(item)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module NoraMark
|
2
|
+
module Html
|
3
|
+
class TagWriter
|
4
|
+
include Util
|
5
|
+
attr_accessor :trailer, :item_preprocessors, :write_body_preprocessors
|
6
|
+
|
7
|
+
def self.create(tag_name, generator, item_preprocessor: nil, write_body_preprocessor: nil, trailer: "\n", chop_last_space: false)
|
8
|
+
instance = TagWriter.new(tag_name, generator, chop_last_space: chop_last_space)
|
9
|
+
instance.item_preprocessors << item_preprocessor unless item_preprocessor.nil?
|
10
|
+
instance.write_body_preprocessors << write_body_preprocessor unless write_body_preprocessor.nil?
|
11
|
+
instance.trailer = trailer
|
12
|
+
yield instance if block_given?
|
13
|
+
instance
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(tag_name, generator, **param)
|
17
|
+
@tag_name = tag_name
|
18
|
+
@generator = generator
|
19
|
+
@context = generator.context
|
20
|
+
@trailer = trailer
|
21
|
+
@item_preprocessors = []
|
22
|
+
@write_body_preprocessors = []
|
23
|
+
@param = param
|
24
|
+
end
|
25
|
+
|
26
|
+
def attr_string(attrs)
|
27
|
+
attrs.map do
|
28
|
+
|name, vals|
|
29
|
+
if vals.size == 0
|
30
|
+
''
|
31
|
+
else
|
32
|
+
" #{name}='#{vals.join(' ')}'"
|
33
|
+
end
|
34
|
+
end.join('')
|
35
|
+
end
|
36
|
+
|
37
|
+
def class_string(cls_array)
|
38
|
+
attr_string({'class' => cls_array})
|
39
|
+
end
|
40
|
+
|
41
|
+
def ids_string(ids_array)
|
42
|
+
attr_string({'id' => ids_array})
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_class(item, cls)
|
46
|
+
(item[:classes] ||= []) << cls
|
47
|
+
end
|
48
|
+
|
49
|
+
def add_class_if_empty(item, cls)
|
50
|
+
add_class(item, cls) if item[:classes].nil? || item[:classes].size == 0
|
51
|
+
end
|
52
|
+
|
53
|
+
def tag_start(item)
|
54
|
+
return if item[:no_tag]
|
55
|
+
ids = item[:ids] || []
|
56
|
+
classes = item[:classes] || []
|
57
|
+
attr = item[:attrs] || {}
|
58
|
+
tag_name = @tag_name || item[:name]
|
59
|
+
@context << "<#{tag_name}#{ids_string(ids)}#{class_string(classes)}#{attr_string(attr)}"
|
60
|
+
if item[:no_body]
|
61
|
+
@context << " />"
|
62
|
+
else
|
63
|
+
@context << ">"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def output(string)
|
68
|
+
@context << string
|
69
|
+
end
|
70
|
+
|
71
|
+
def tag_end(item)
|
72
|
+
return if item[:no_tag]
|
73
|
+
tag_name = @tag_name || item[:name]
|
74
|
+
@context << "</#{tag_name}>#{@trailer}"
|
75
|
+
end
|
76
|
+
|
77
|
+
def write(item)
|
78
|
+
@item_preprocessors.each { |x| item = instance_exec item.dup, &x }
|
79
|
+
@context.enable_pgroup, saved_ep = !(item[:args].include?('wo-pgroup') || !@context.enable_pgroup), @context.enable_pgroup
|
80
|
+
tag_start item
|
81
|
+
write_body item if !item[:no_body]
|
82
|
+
tag_end item if !item[:no_body]
|
83
|
+
@context.enable_pgroup = saved_ep
|
84
|
+
end
|
85
|
+
|
86
|
+
def write_body(item)
|
87
|
+
@write_body_preprocessors.each {
|
88
|
+
|x|
|
89
|
+
return if instance_exec(item, &x) == :done
|
90
|
+
}
|
91
|
+
write_children item
|
92
|
+
end
|
93
|
+
|
94
|
+
def write_children(item)
|
95
|
+
write_array(item[:children])
|
96
|
+
end
|
97
|
+
|
98
|
+
def write_array(array)
|
99
|
+
return if array.nil? || array.size == 0
|
100
|
+
array.each { |x| @generator.to_html x }
|
101
|
+
@generator.context.chop_last_space if (@param[:chop_last_space])
|
102
|
+
end
|
103
|
+
|
104
|
+
def children_not_empty(item)
|
105
|
+
!item[:children].nil? && item[:children].size > 0 && item[:children].select { |x| (x.is_a? String) ? x.size >0 : !x.nil? }.size > 0
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module NoraMark
|
2
|
+
module Html
|
3
|
+
class WriterSelector
|
4
|
+
def initialize(generator, tag_writers = {}, trailer_default: "\n" )
|
5
|
+
@generator = generator
|
6
|
+
@common_tag_writer = TagWriter.create(nil, @generator, trailer: trailer_default)
|
7
|
+
@tag_writers = tag_writers
|
8
|
+
if !trailer_default.nil?
|
9
|
+
@tag_writers.each { |k, t|
|
10
|
+
if t.is_a? TagWriter
|
11
|
+
t.trailer = trailer_default
|
12
|
+
end
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
def write(item)
|
19
|
+
writer = @tag_writers[item[:name]] || @common_tag_writer
|
20
|
+
writer.write(item)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
%% name = NoraMark::Parser
|
2
|
+
|
3
|
+
# literals
|
4
|
+
eof = !.
|
5
|
+
space = ' ' | '\t'
|
6
|
+
eof_comment = lh space* "#" (!eof .)*
|
7
|
+
comment = lh space* "#" (!nl .)* nl empty_line*
|
8
|
+
- = ( space | comment )*
|
9
|
+
empty_line = lh - nl
|
10
|
+
nl = /\r?\n/
|
11
|
+
lh = /^/
|
12
|
+
le = nl | eof
|
13
|
+
word = < /[\w0-9]/ ( '-' | /[\w0-9]/ )* > { text }
|
14
|
+
num = < [0-9]+ > { text.to_i }
|
15
|
+
|
16
|
+
|
17
|
+
#common syntax
|
18
|
+
classname = '.' word:classname { classname }
|
19
|
+
classnames = (classname)*:classnames { classnames }
|
20
|
+
idname = '#' word:idname { idname }
|
21
|
+
idnames = (idname)*:idnames { idnames }
|
22
|
+
|
23
|
+
commandname = word:name idnames?:idnames classnames?:classes { {:name => name, :ids => idnames, :classes => classes} }
|
24
|
+
parameter = < ( /[^,)]/* | '"' /[^"]/* '"' | "'" /[^']/* "'" ) > { text }
|
25
|
+
parameters = < parameter (',' parameter)* > { text }
|
26
|
+
command = commandname:cn ('(' - parameters:arg - ')')? { arg ||= ''; cn.merge({ :args => arg.split(',') }) }
|
27
|
+
|
28
|
+
# paragraph
|
29
|
+
implicit_paragraph = < (!paragraph_delimiter - documentline:p -) > { create_item(:paragraph, nil, p, raw: text) }
|
30
|
+
paragraph = explicit_paragraph | implicit_paragraph
|
31
|
+
|
32
|
+
# paragraph_group
|
33
|
+
paragraph_group = < paragraph+:p empty_line* > { create_item(:paragraph_group, nil, p, raw: text) }
|
34
|
+
|
35
|
+
# explicit block
|
36
|
+
blockhead = lh - command:command - '{' - nl empty_line* { command }
|
37
|
+
blockend = lh - '}' - le empty_line*
|
38
|
+
blockbody = (!blockend block)+:body { body }
|
39
|
+
explicit_block = < blockhead:head - blockbody:body - blockend > { create_item(:block, head, body, raw: text) }
|
40
|
+
|
41
|
+
# preformatted block
|
42
|
+
preformatted_command = command:command &{ ['pre', 'precode'].include? command[:name] }
|
43
|
+
preformatted_command_head = lh - preformatted_command:command - '<<' &/[\w0-9]/ { command }
|
44
|
+
preformat_end(start) = lh word:delimiter &{ delimiter == start }
|
45
|
+
preformatted_block = < lh - preformatted_command_head:command !nl word:delimiter nl (!preformat_end(delimiter) (lh charstring nl))+:content preformat_end(delimiter) > { create_item(:preformatted, command, content, raw: text) }
|
46
|
+
|
47
|
+
# inline command
|
48
|
+
inline = img_inline | common_inline
|
49
|
+
common_inline = < '[' command:c '{' documentcontent_except('}'):content '}' ']' > { create_item(:inline, c, content, raw: text) }
|
50
|
+
img_command = command:c &{ c[:name] == 'img' && c[:args].size == 2}
|
51
|
+
img_inline = < '[' img_command:c ']' > { create_item(:inline, c, nil, raw: text) }
|
52
|
+
|
53
|
+
# special line commands
|
54
|
+
commandname_for_special_line_command = newpage_command | explicit_paragraph_command
|
55
|
+
|
56
|
+
# newpage
|
57
|
+
newpage_command = command:command &{ command[:name] == 'newpage' }
|
58
|
+
newpage = < lh - newpage_command:c ':' documentcontent?:content - nl > { create_item(:newpage, c, content, raw:text) }
|
59
|
+
|
60
|
+
# explicit paragraph
|
61
|
+
explicit_paragraph_command = command:c &{ c[:name] == 'p' }
|
62
|
+
explicit_paragraph = < lh - explicit_paragraph_command:c ':' documentcontent?:content le empty_line*> { create_item(:paragraph, c, content, raw:text) }
|
63
|
+
|
64
|
+
|
65
|
+
# unordered list
|
66
|
+
unordered_list = < unordered_item+:items > { create_item(:ul, nil, items, raw: text) }
|
67
|
+
unordered_item = < lh '*:' documentcontent:content le > { create_item(:li, nil, content, raw: text) }
|
68
|
+
|
69
|
+
# ordered list
|
70
|
+
ordered_list = < ordered_item+:items > { create_item(:ol, nil, items, raw: text) }
|
71
|
+
ordered_item = < lh num ':' documentcontent:content le > { create_item(:li, nil, content, raw: text) }
|
72
|
+
|
73
|
+
# definition list
|
74
|
+
definition_list = < definition_item+:items > { create_item(:dl, nil, items, raw: text) }
|
75
|
+
definition_item = < lh ';:' - documentcontent_except(':'):term ':' - documentcontent:definition le > { create_item(:dtdd, {:args => [term, definition]}, nil, raw: text) }
|
76
|
+
|
77
|
+
items_list = unordered_list | ordered_list | definition_list
|
78
|
+
|
79
|
+
|
80
|
+
# generic line command
|
81
|
+
line_command = < lh - !commandname_for_special_line_command command:c ':' documentcontent?:content - le empty_line* > { create_item(:line_command, c, content, raw: text) }
|
82
|
+
|
83
|
+
# blocks
|
84
|
+
line_block = items_list | line_command
|
85
|
+
block = (preformatted_block | headed_section | line_block | explicit_block | paragraph_group ):block empty_line* {block}
|
86
|
+
block_delimiter = blockhead | blockend
|
87
|
+
paragraph_delimiter = block_delimiter | preformatted_command_head | line_block | newpage | headed_start
|
88
|
+
|
89
|
+
# markdown-style headings
|
90
|
+
h_start_mark(n) = < '='+ ':' > &{ text.length - 1 == n }
|
91
|
+
h_markup_terminator(n) = lh - < '='+ ':' > &{ text.length - 1 <= n }
|
92
|
+
|
93
|
+
h_start(n) = lh - h_start_mark(n) charstring:s le { { level: n, heading: s } }
|
94
|
+
h_section(n) = < h_start(n):h (!h_markup_terminator(n) !eof block)+:content > { create_item(:h_section, h, content, raw: text) }
|
95
|
+
|
96
|
+
headed_start = h_start(1) | h_start(2) | h_start(3) | h_start(4) | h_start(5) | h_start(6)
|
97
|
+
headed_section = h_section(1) | h_section(2)| h_section(3)| h_section(4)| h_section(5) | h_section(6)
|
98
|
+
|
99
|
+
#header
|
100
|
+
stylesheets = < lh - 'stylesheets:' !le charstring:s nl > { create_item(:stylesheets, {:stylesheets => s.split(',').map(&:strip)}, nil, raw:text) }
|
101
|
+
title = < lh - 'title:' !le charstring:t nl > { create_item(:title, {:title => t }, nil, raw:text) }
|
102
|
+
lang = < lh - 'lang:' !le charstring:l nl > { create_item(:lang, {:lang => l }, nil, raw:text) }
|
103
|
+
paragraph_style = < lh - 'paragraph-style:' !le charstring:l nl > { create_item(:paragraph_style, {:paragraph_style => l }, nil, raw:text) }
|
104
|
+
header = (stylesheets | title | lang | paragraph_style ) empty_line*
|
105
|
+
|
106
|
+
# texts
|
107
|
+
char = < /[[:print:]]/ > { text }
|
108
|
+
charstring = < char* > { text }
|
109
|
+
char_except(e) = char:c &{ c != e }
|
110
|
+
charstring_except(e) = < char_except(e)* > { text }
|
111
|
+
documentcontent_except(e) = (inline | !inline char_except(e))+:content ~parse_text(content)
|
112
|
+
documentcontent = (inline | !inline char)+:content ~parse_text(content)
|
113
|
+
documentline = lh documentcontent:content le { content }
|
114
|
+
|
115
|
+
#page
|
116
|
+
headers = header*:headers { create_item(:headers, nil, headers) }
|
117
|
+
page = headers:headers - (!newpage block)*:blocks { create_item(:page, nil, [headers] + blocks.select{ |x| !x.nil?}) }
|
118
|
+
newpaged_page = newpage:newpage page:page { page[:children] = page[:children].unshift newpage; page }
|
119
|
+
#root
|
120
|
+
root = page:page newpaged_page*:pages - eof_comment? eof { [ page ] + pages }
|
121
|
+
|
122
|
+
|
123
|
+
|