nora_mark 0.2beta3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,12 @@
1
+ module NoraMark
2
+ module Html
3
+ module Util
4
+ def escape_html(string)
5
+ string.to_s.gsub("&", "&amp;").
6
+ gsub("<", "&lt;").
7
+ gsub(">", "&gt;").
8
+ gsub('"', "&quot;")
9
+ end
10
+ end
11
+ end
12
+ 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
+