arti_mark 0.0.1.beta4 → 0.1.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: abd2001b34dc838a27ba1c9f1e188fde512e2468
4
- data.tar.gz: 3d683b3d4c7e09efd3414ab6c62503d09d804503
3
+ metadata.gz: 62679290ba21c0b408d4fff89c820958fa789ff6
4
+ data.tar.gz: a16462606130c072726ce1d86bb0e677ce267ed3
5
5
  SHA512:
6
- metadata.gz: a01c7e24864ca6fa710ca1b22e13c3c8e00f2ab13d2aa0036aa268be4501d63c82266d5a7192dc7420750816495417b46ca9d8090037c817711558037a592d14
7
- data.tar.gz: 51e4d4bef90306fb68f879fcaf8db6305bc54a6b52a402f50b62cf4db2628d963352a9bfeac09a75e14e8973014152aab239dd53812fbfd88a09dc648f110976
6
+ metadata.gz: 33bdc6ff8f9b6bf47352876b60fbac750a6ea4f616c9f85197af9ce9a08d9773ac33ef6450ee4f63b33ac6bb6696eefa03a7f394c6d46243eb9ced1cc8977122
7
+ data.tar.gz: 946a6ef094042486ab500081851c7d8d19e613ae356d5fe0fc98c67eeb3780fe9dd271543f98f6a0cb2f9655849b6976d195126f02c6c951b9efd79c3c555e1c
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # version 0.1beta1 (pre NoraText)
2
+
3
+ * Totally rewrite using kpeg.
4
+ * degrage : toc feature removed (for the old toc feature is so poor)
5
+ * degrade : removed custom BlockParser. Instead of the feature, easy and powerful customization will be introduced in NoraText 0.1)
6
+ * markup change: alternate block notation starting with 'd{---' has removed
7
+ * markup change: inline image notation is changed form [img(alt-text){src}] to [img(src, alt)]
8
+
9
+ * will change the name from ArtiMark to NoraText on next release 0.1rc1
10
+
11
+
12
+
data/README.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  ArtiMark is a simple text markup language. It is designed to create XHTML files for EPUB books. It is optimized for Japanese text for the present.
4
4
 
5
- **CAUTION This is very early alpha version, so it's not stable at all. Even the markup syntax will change. **
5
+ **CAUTION This is very early alpha version, so it's not stable at all.**
6
6
 
7
- I hope it will be partly stable by the end of Feburary, 2013
7
+ Reimplemented new version will be released on the end of Feb. 2014. Some syntax will be changed on the new version. The name of the library may change.
8
8
 
9
9
  ## Installation
10
10
 
data/Rakefile CHANGED
@@ -1,2 +1,12 @@
1
1
  #!/usr/bin/env rake
2
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/arti_mark/parser.kpeg.rb"] do
11
+ system 'rspec'
12
+ end
data/arti_mark.gemspec CHANGED
@@ -15,6 +15,8 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = ArtiMark::VERSION
17
17
 
18
- gem.add_development_dependency "rspec", "~> 2.11"
19
- gem.add_development_dependency "nokogiri", "~> 1.5.6"
18
+ gem.required_ruby_version = '>= 2.0.0'
19
+ gem.add_dependency "kpeg"
20
+ gem.add_development_dependency "rspec", "~> 2.14"
21
+ gem.add_development_dependency "nokogiri", "~> 1.6.0"
20
22
  end
@@ -19,8 +19,8 @@ module ArtiMark
19
19
 
20
20
  r << "<div#{ids_string(lexed[:ids])}#{class_string(lexed[:cls])}>"
21
21
  r << "<p>#{caption}</p>" if !caption.nil? && caption.size > 0 && caption_before
22
- r << "<img src='#{src}' alt='#{alt}' />"
23
- r << "<p>#{caption}</p>" if !caption.nil? && caption.size > 0 && !caption_before
22
+ r << "<img src='#{src}' alt='#{escape_html alt}' />"
23
+ r << "<p>#{escape_html caption}</p>" if !caption.nil? && caption.size > 0 && !caption_before
24
24
  r << "</div>\n"
25
25
  end
26
26
  end
@@ -1,4 +1,5 @@
1
1
  module ArtiMark
2
+ module Html
2
3
  class Context
3
4
  attr_accessor :title, :head_inserters, :toc, :lang, :stylesheets, :enable_pgroup
4
5
  def initialize(param = {})
@@ -25,7 +26,10 @@ module ArtiMark
25
26
  ret
26
27
  end
27
28
  end
28
-
29
+ def chop_last_space
30
+ @pages.last.sub!(/[[:space:]]+$/, '')
31
+ end
32
+
29
33
  def head_inserter(&block)
30
34
  head_inserters << block
31
35
  end
@@ -91,3 +95,4 @@ module ArtiMark
91
95
  end
92
96
  end
93
97
  end
98
+ end
@@ -0,0 +1,159 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'arti_mark/html/util'
3
+ require 'arti_mark/html/result'
4
+ require 'arti_mark/html/context'
5
+ require 'arti_mark/html/tag_writer'
6
+ require 'arti_mark/html/header_writer'
7
+ require 'arti_mark/html/writer_selector'
8
+ module ArtiMark
9
+ module Html
10
+ class Generator
11
+ include Util
12
+ attr_reader :context
13
+ def initialize(param = {})
14
+ @context = Context.new(param)
15
+ article_writer = TagWriter.create('article', self)
16
+ link_writer = TagWriter.create('a', self, trailer: '',
17
+ item_preprocessor: proc do |item|
18
+ (item[:attrs] ||= {}).merge!({:href => [ item[:args][0] ]})
19
+ item
20
+ end)
21
+
22
+ header_writer = HeaderWriter.new self
23
+
24
+ @writers = {
25
+ :paragraph =>
26
+ TagWriter.create('p', self, chop_last_space: true,
27
+ item_preprocessor: proc do |item|
28
+ add_class(item, 'noindent') if item[:children][0] =~/^(「|『|()/ # TODO: should be plaggable}
29
+ item
30
+ end
31
+ ),
32
+ :paragraph_group =>
33
+ TagWriter.create("div", self,
34
+ item_preprocessor: proc do |item|
35
+ add_class item, 'pgroup'
36
+ item[:no_tag] = true unless @context.enable_pgroup
37
+ item
38
+ end
39
+ ),
40
+
41
+ :block =>
42
+ WriterSelector.new(self,
43
+ {
44
+ 'd' => TagWriter.create('div', self),
45
+ 'art' => article_writer,
46
+ 'article' => article_writer
47
+ }),
48
+ :line_command =>
49
+ WriterSelector.new(self,
50
+ {
51
+ 'image' =>
52
+ TagWriter.create('div', self,
53
+ item_preprocessor: proc do |item|
54
+ add_class_if_empty item, 'img-wrap'
55
+ item
56
+ end,
57
+ write_body_preprocessor: proc do |item|
58
+ src = item[:args][0].strip
59
+ alt = (item[:args][1] || '').strip
60
+ caption_before = item[:named_args][:caption_before]
61
+ if caption_before && children_not_empty(item)
62
+ output "<p>"; write_children item; output "</p>"
63
+ end
64
+ output "<img src='#{src}' alt='#{escape_html alt}' />"
65
+ if !caption_before && children_not_empty(item)
66
+ output "<p>"; write_children item; output "</p>"
67
+ end
68
+ :done
69
+ end
70
+ ),
71
+ 'newpage' =>
72
+ TagWriter.create('div', self,
73
+ item_preprocessor: proc do |item|
74
+ item[:no_tag] = true
75
+ item
76
+ end,
77
+ write_body_preprocessor: proc do |item|
78
+ title = nil
79
+ if item[:args].size > 0 && item[:args][0].size > 0
80
+ title = escape_html item[:args].first
81
+ end
82
+ @context.start_html(title)
83
+ :done
84
+ end
85
+ ),
86
+
87
+ }),
88
+ :inline =>
89
+ WriterSelector.new(self,
90
+ {
91
+ 'link' => link_writer,
92
+ 'l' => link_writer,
93
+ 's' => TagWriter.create('span', self),
94
+ 'img' =>
95
+ TagWriter.create('img', self,
96
+ item_preprocessor: proc do |item|
97
+ 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}
98
+ (item[:attrs] ||= {}).merge!({:src => [item[:args][0] ]})
99
+ item[:attrs].merge!({:alt => [ escape_html(item[:args][1].strip)]}) if (item[:args].size > 1 && item[:args][1].size > 0)
100
+ item
101
+ end) ,
102
+ 'tcy' =>
103
+ TagWriter.create('span', self,
104
+ item_preprocessor: proc do |item|
105
+ add_class item, 'tcy'
106
+ item
107
+ end),
108
+ 'ruby' =>
109
+ TagWriter.create('ruby', self,
110
+ write_body_preprocessor: proc do |item|
111
+ write_children item
112
+ output "<rp>(</rp><rt>#{escape_html item[:args][0].strip}</rt><rp>)</rp>"
113
+ :done
114
+ end),
115
+
116
+ },
117
+ trailer_default:''
118
+ ),
119
+ :ol => TagWriter.create('ol', self),
120
+ :ul => TagWriter.create('ul', self),
121
+ :li => TagWriter.create('li', self),
122
+ :dl => TagWriter.create('dl', self),
123
+ :dtdd =>
124
+ TagWriter.create('', self, chop_last_space: true, item_preprocessor: proc do |item| item[:no_tag] = true; item end,
125
+ write_body_preprocessor: proc do |item|
126
+ output "<dt>"; write_array item[:args][0]; output "</dt>"
127
+ output "<dd>"; write_array item[:args][1]; output "</dd>"
128
+ :done
129
+ end),
130
+ # headers
131
+ :stylesheets => header_writer,
132
+ :title => header_writer,
133
+ :lang => header_writer,
134
+ }
135
+ end
136
+
137
+ def convert(parsed_result)
138
+ parsed_result.each {
139
+ |item|
140
+ to_html(item)
141
+ }
142
+ @context.result
143
+ end
144
+ def to_html(item)
145
+ if item.is_a? String
146
+ @context << escape_html(item)
147
+ else
148
+ writer = @writers[item[:type]]
149
+ if writer.nil?
150
+ warn "can't find html generator for \"#{item}\""
151
+ @context << escape_html(item[:raw_text])
152
+ else
153
+ writer.write(item)
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,32 @@
1
+ module ArtiMark
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
+ }
26
+ end
27
+ def write(item)
28
+ @writers[item[:type]].call item
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,27 @@
1
+ module ArtiMark
2
+ module Html
3
+ class Context
4
+ class Result < Array
5
+ def initialize
6
+ super
7
+ end
8
+
9
+ def write_as_files(prefix, format='%03d')
10
+ self.each_with_index {
11
+ |converted, i|
12
+ File.open("#{prefix}_#{format%(i+1)}.xhtml", 'w+') {
13
+ |file|
14
+ file << converted
15
+ }
16
+ }
17
+ end
18
+ def write_as_single_file(filename)
19
+ File.open(filename, 'w+') {
20
+ |file|
21
+ file << self[0]
22
+ }
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,110 @@
1
+ module ArtiMark
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 ArtiMark
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 ArtiMark
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,97 @@
1
+ %% name = ArtiMark::Parser
2
+
3
+ # literals
4
+ eof = !.
5
+ space = ' ' | '\t'
6
+ eof_comment = lh space* "#" (!eof .)*
7
+ comment = lh space* "#" (!nl .)* nl
8
+
9
+ - = ( space | comment )*
10
+ empty_line = lh - nl
11
+ nl = /\r?\n/
12
+ lh = /^/
13
+ le = nl | /$/
14
+ word = < /[\w0-9]/ ( '-' | /[\w0-9]/ )* > { text }
15
+ num = < [0-9]+ > { text.to_i }
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:commandname ('(' - parameters:arg - ')')? { arg ||= ''; commandname.merge({ :args => arg.split(',') }) }
27
+
28
+ # paragraph
29
+ implicit_paragraph = < (!paragraph_delimiter - documentline - ):paragraph > { create_item(:paragraph, nil, paragraph, raw: text) }
30
+ paragraph = explicit_paragraph | implicit_paragraph
31
+
32
+ # paragraph_group
33
+ paragraph_group = < (paragraph nl | paragraph )+:paragraphs empty_line* > { create_item(:paragraph_group, nil, paragraphs, raw: text) }
34
+
35
+ # explicit block
36
+ blockhead = lh - command:command - '{' - le { command }
37
+ blockend = lh - '}' - le
38
+ blockbody = (!blockend block)+:body { body }
39
+ explicit_block = < blockhead:head blockbody:body blockend > { create_item(:block, head, body, raw: text) }
40
+
41
+ # inline command
42
+ inline = img_inline | common_inline
43
+ common_inline = < '[' command:command '{' documentcontent_except('}'):content '}' ']' > { create_item(:inline, command, content, raw: text) }
44
+
45
+ #img inline
46
+ img_command = command:command &{ command[:name] == 'img' && command[:args].size == 2}
47
+ img_inline = < '[' img_command:command ']' > { create_item(:inline, command, nil, raw: text) }
48
+
49
+ # special line commands
50
+ # newpage
51
+ newpage = line_command:item &{ item[:name] == 'newpage' }
52
+ # explicit paragraph
53
+ explicit_paragraph_command = command:command &{ command[:name] == 'p' }
54
+ explicit_paragraph = < lh - explicit_paragraph_command:command ':' documentcontent?:content le > { create_item(:paragraph, command, content, raw:text) }
55
+
56
+ # unordered list
57
+ unordered_list = < unordered_item+:items > { create_item(:ul, nil, items, raw: text) }
58
+ unordered_item = < lh '*:' documentcontent:content le > { create_item(:li, nil, content, raw: text) }
59
+
60
+ # ordered list
61
+ ordered_list = < ordered_item+:items > { create_item(:ol, nil, items, raw: text) }
62
+ ordered_item = < lh num ':' documentcontent:content le > { create_item(:li, nil, content, raw: text) }
63
+
64
+ # definition list
65
+ definition_list = < definition_item+:items > { create_item(:dl, nil, items, raw: text) }
66
+ definition_item = < lh ';:' - documentcontent_except(':'):term ':' - documentcontent:definition le > { create_item(:dtdd, {:args => [term, definition]}, nil, raw: text) }
67
+
68
+ items_list = unordered_list | ordered_list | definition_list
69
+
70
+
71
+ # generic line command
72
+ line_command = < lh - (!explicit_paragraph_command command):command ':' documentcontent?:content le > { create_item(:line_command, command, content, raw: text) }
73
+
74
+ # blocks
75
+ block = items_list | line_command | explicit_block | paragraph_group | empty_line+
76
+ block_delimiter = blockhead | blockend | newpage
77
+ paragraph_delimiter = block | block_delimiter
78
+
79
+ # texts
80
+ char = < /[[:print:]]/ > { text }
81
+ charstring = < char* > { text }
82
+ char_except(e) = char:c &{ c != e }
83
+ charstring_except(e) = < char_except(e)* > { text }
84
+ documentcontent_except(e) = (inline | !inline char_except(e))+:content ~parse_text(content)
85
+ documentcontent = (inline | !inline char)+:content ~parse_text(content)
86
+ documentline = lh documentcontent:content /$/ { content }
87
+
88
+ #header
89
+ stylesheets = < lh - 'stylesheets:' (!le charstring):stylesheets le > { create_item(:stylesheets, {:stylesheets => stylesheets.split(',').map(&:strip)}, nil, raw:text) }
90
+ title = < lh - 'title:' (!le charstring):title le > { create_item(:title, {:title => title }, nil, raw:text) }
91
+ lang = < lh - 'lang:' (!le charstring):lang le > { create_item(:lang, {:lang => lang }, nil, raw:text) }
92
+ header = stylesheets | title | lang
93
+
94
+ #root
95
+ root = header*:headers block*:blocks eof_comment? eof { headers + blocks }
96
+
97
+