ulysses 0.3.3 → 0.4.0
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 +4 -4
- data/README.md +2 -0
- data/lib/ulysses.rb +2 -1
- data/lib/ulysses/group.rb +37 -20
- data/lib/ulysses/library.rb +13 -2
- data/lib/ulysses/printer.rb +108 -0
- data/lib/ulysses/printer/elements.rb +69 -0
- data/lib/ulysses/sheet.rb +27 -9
- data/lib/ulysses/version.rb +1 -1
- metadata +4 -3
- data/lib/ulysses/exporter.rb +0 -287
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c7b1d519c285491fa42fda0e4f870252021883b
|
4
|
+
data.tar.gz: 38235905aa64dc7ead038ec120bbfb0daaf116c3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4ea24651011856c59aa05c7a6d6129b2c256c7b60b42d0a117d77273b772f044f85b32d7686549a6436383f57d2540c1061bd3a0f83bf3dda1450643de902e05
|
7
|
+
data.tar.gz: b64626d3d96e51b58d2e4be8fd58ea6c3ab081fb9f1ad44e9055c69d91a16086cde221d77b86882b7cec816b02dd2b1baa8f40fd2228cce961456a9ec30f9072
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Ulysses
|
2
2
|
|
3
|
+
[](https://gitter.im/yaodong/gem-ulysses?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](https://codeclimate.com/github/yaodong/gem-ulysses)
|
4
|
+
|
3
5
|
This is a library to export your to HTML files. It still in development.
|
4
6
|
|
5
7
|
## Installation
|
data/lib/ulysses.rb
CHANGED
data/lib/ulysses/group.rb
CHANGED
@@ -4,41 +4,58 @@ module Ulysses
|
|
4
4
|
attr_reader :dirname
|
5
5
|
|
6
6
|
def initialize(info_file_path)
|
7
|
-
@
|
8
|
-
@
|
7
|
+
@info_file = info_file_path
|
8
|
+
@dirname = File.dirname(@info_file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def info
|
12
|
+
@info ||= parse_info
|
9
13
|
end
|
10
14
|
|
11
15
|
def display_name
|
12
|
-
@display_name
|
16
|
+
@display_name ||= info['displayName'].content
|
13
17
|
end
|
14
18
|
|
15
19
|
def children
|
16
|
-
|
17
|
-
@info['childOrder'].children.map do |child|
|
18
|
-
Group.new File.join(@dirname, child.content, 'Info.ulgroup') if child.element?
|
19
|
-
end.compact
|
20
|
+
@children ||= parse_children
|
20
21
|
end
|
22
|
+
alias :groups :children
|
21
23
|
|
22
24
|
def sheets
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
list.map do |dirname|
|
29
|
-
Sheet.new File.join(@dirname, dirname)
|
30
|
-
end
|
25
|
+
@sheets ||= parse_sheets
|
26
|
+
end
|
27
|
+
|
28
|
+
def reload
|
29
|
+
@info, @children, @sheets = nil
|
31
30
|
end
|
32
31
|
|
33
32
|
private
|
34
33
|
|
35
|
-
def parse_info
|
36
|
-
xml = Nokogiri::XML File.read(
|
37
|
-
dict = xml.xpath('//dict')
|
38
|
-
|
39
|
-
|
34
|
+
def parse_info
|
35
|
+
xml = Nokogiri::XML File.read(@info_file)
|
36
|
+
dict = xml.xpath('//dict')
|
37
|
+
.children
|
38
|
+
.select { |child| child.element? }
|
39
|
+
.map { |child| child.name == 'key' ? child.content : child }
|
40
40
|
Hash[*dict]
|
41
41
|
end
|
42
42
|
|
43
|
+
def parse_sheets
|
44
|
+
return [] unless info['sheetClusters']
|
45
|
+
info['sheetClusters']
|
46
|
+
.children
|
47
|
+
.select { |c| c.element? && c.name == 'array' }
|
48
|
+
.map { |i| i.children.find { |c| c.element? && c.name == 'string' }.content }
|
49
|
+
.map { |dir| Sheet.new File.join(@dirname, dir) }
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_children
|
53
|
+
return [] unless info['childOrder']
|
54
|
+
info['childOrder']
|
55
|
+
.children
|
56
|
+
.select { |child| child.element? }
|
57
|
+
.map { |child| Group.new File.join(@dirname, child.content, 'Info.ulgroup') }
|
58
|
+
end
|
59
|
+
|
43
60
|
end
|
44
61
|
end
|
data/lib/ulysses/library.rb
CHANGED
@@ -1,14 +1,25 @@
|
|
1
1
|
module Ulysses
|
2
2
|
class Library
|
3
3
|
|
4
|
+
DEFAULT_LIBRARY_DIR = '~/Library/Mobile Documents/X5AZV975AG~com~soulmen~ulysses3/Documents/Library'
|
5
|
+
|
4
6
|
attr_reader :dirname
|
5
7
|
|
6
8
|
def initialize(dirname = nil)
|
7
|
-
dirname ||=
|
8
|
-
@dirname = File.expand_path(dirname)
|
9
|
+
@dirname = File.expand_path(dirname ||= DEFAULT_LIBRARY_DIR)
|
9
10
|
end
|
10
11
|
|
11
12
|
def groups
|
13
|
+
@groups ||= parse_groups
|
14
|
+
end
|
15
|
+
|
16
|
+
def reload
|
17
|
+
@groups = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_groups
|
12
23
|
Dir.glob(File.join @dirname, 'Groups-ulgroup', '*.ulgroup').map do |info_file|
|
13
24
|
Group.new info_file
|
14
25
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module Ulysses
|
2
|
+
class Printer
|
3
|
+
|
4
|
+
SHEET_CONTENT_XPATH = '/sheet/string[@xml:space="preserve"]'
|
5
|
+
|
6
|
+
def initialize(target)
|
7
|
+
@target = target
|
8
|
+
@footnotes = []
|
9
|
+
@annotations = []
|
10
|
+
@html_entities = HTMLEntities.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def print
|
14
|
+
if @target.is_a? Library
|
15
|
+
print_library(@target)
|
16
|
+
elsif @target.is_a? Group
|
17
|
+
print_group(@target)
|
18
|
+
elsif @target.is_a? Sheet
|
19
|
+
print_sheet(@target)
|
20
|
+
else
|
21
|
+
raise "Unsupported print type: #{@target.class}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def footnotes
|
26
|
+
@footnotes
|
27
|
+
end
|
28
|
+
|
29
|
+
def annotations
|
30
|
+
@annotations
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def print_library(library)
|
36
|
+
library.groups.map { |g| print_group(g) }.join("\n")
|
37
|
+
end
|
38
|
+
|
39
|
+
def print_group(group)
|
40
|
+
group.sheets.map { |s| print_sheet(s) }.join("\n") + group.groups.map { |g| print_group(g) }.join("\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
def print_sheet(sheet)
|
44
|
+
paragraphs = sheet.xml.xpath(SHEET_CONTENT_XPATH).children.select { |n| n.element? }
|
45
|
+
paragraphs.map{ |p| print_paragraph(p) }.join("\n")
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_paragraph(p)
|
49
|
+
children = p.children
|
50
|
+
tags = (children.any? && children.first.name === 'tags') ? parse_tags(children.shift) : []
|
51
|
+
content = parse_content(children)
|
52
|
+
|
53
|
+
tabs = tags.count('tab')
|
54
|
+
if tabs > 0
|
55
|
+
tags.delete('tab')
|
56
|
+
tags << "tabs_#{tabs}"
|
57
|
+
end
|
58
|
+
tags = tags.uniq.map{|t| normalize_tag(t)}.join(' ')
|
59
|
+
"<p class=\"#{tags}\">#{content}</p>"
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse_content(nodes)
|
63
|
+
nodes.map do |node|
|
64
|
+
if node.text?
|
65
|
+
node.content
|
66
|
+
else
|
67
|
+
send("parse_#{node.name}", node)
|
68
|
+
end
|
69
|
+
end.join
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_tags(tags)
|
73
|
+
tags.children.map do |tag|
|
74
|
+
if tag.attributes.has_key? 'kind'
|
75
|
+
tag.attributes['kind'].value
|
76
|
+
elsif tag.content === "\t"
|
77
|
+
'tab'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def parse_escape(node)
|
83
|
+
node.content.gsub /\\(.)/, '\1'
|
84
|
+
end
|
85
|
+
|
86
|
+
def parse_p(node)
|
87
|
+
'<p>' + parse_content(node.children) + '</p>'
|
88
|
+
end
|
89
|
+
|
90
|
+
def parse_string(node)
|
91
|
+
parse_content node.children
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_element(node)
|
95
|
+
send "parse_element_#{node.attributes['kind'].value}", node
|
96
|
+
end
|
97
|
+
|
98
|
+
def normalize_tag(tag)
|
99
|
+
tag.gsub(/::/, '/')
|
100
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
101
|
+
.gsub(/([a-z\d])([A-Z])/,'\1_\2')
|
102
|
+
.gsub(/([a-z])(\d)/i, '\1_\2')
|
103
|
+
.tr('-', '_')
|
104
|
+
.downcase
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Ulysses
|
2
|
+
class Printer
|
3
|
+
|
4
|
+
def parse_element_strong(node)
|
5
|
+
'<strong>' + node.content + '</strong>'
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse_element_emph(node)
|
9
|
+
'<em>' + node.content + '</em>'
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_element_mark(node)
|
13
|
+
'<span class="marked">' + node.content + '</span>'
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse_element_delete(node)
|
17
|
+
'<del>' + node.content + '</del>'
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_element_inlineComment(node)
|
21
|
+
'<span class="inline-comment">' + node.content + '</span>'
|
22
|
+
end
|
23
|
+
|
24
|
+
def parse_element_code(node)
|
25
|
+
'<code>' + node.content + '</code>'
|
26
|
+
end
|
27
|
+
|
28
|
+
def parse_element_inlineNative(node)
|
29
|
+
'<span class="inline-native">' + node.content + '</span>'
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_element_link(node)
|
33
|
+
attrs = parse_element_attributes(node)
|
34
|
+
content = parse_content(node.children.select{ |child| !child.element? || child.name != 'attribute' })
|
35
|
+
'<a href="' + attrs.fetch('URL', '') + '" title="' + attrs.fetch('title', '') + '">' + content + '</a>'
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_element_image(node)
|
39
|
+
attrs = parse_element_attributes(node)
|
40
|
+
'<img src="' + attrs.fetch('URL', '') + '" alt="' + attrs.fetch('title', '') + '" />'
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_element_video(node)
|
44
|
+
attrs = parse_element_attributes(node)
|
45
|
+
'<video><source src="' + attrs['URL'] + '" /></video>'
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_element_footnote(node)
|
49
|
+
attrs = parse_element_attributes(node)
|
50
|
+
@footnotes << attrs['text']
|
51
|
+
'<sup class="footnote-ref"><a href="#fn' + @footnotes.size.to_s + '">' + @footnotes.size.to_s + '</a></sup>'
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_element_annotation(node)
|
55
|
+
attrs = parse_element_attributes(node)
|
56
|
+
@annotations << attrs['text']
|
57
|
+
'<span class="annotation" data-id="' + @annotations.size.to_s + '">' + @annotations.size.to_s + '</span>'
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_element_attributes(element)
|
61
|
+
attributes = element.children.select { |child| child.element? && child.name === 'attribute' }
|
62
|
+
attributes.map! do |attr|
|
63
|
+
[attr.attributes['identifier'].value, parse_content(attr.children)]
|
64
|
+
end
|
65
|
+
Hash[attributes]
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
data/lib/ulysses/sheet.rb
CHANGED
@@ -7,21 +7,39 @@ module Ulysses
|
|
7
7
|
@dirname = dirname
|
8
8
|
end
|
9
9
|
|
10
|
-
def
|
11
|
-
@
|
12
|
-
@text = nil
|
10
|
+
def markup
|
11
|
+
@markup ||= parse_markup
|
13
12
|
end
|
14
13
|
|
15
|
-
def
|
16
|
-
@
|
14
|
+
def xml
|
15
|
+
@xml ||= Nokogiri::XML(File.read(File.join(@dirname, 'Content.xml')))
|
17
16
|
end
|
18
17
|
|
19
|
-
def
|
20
|
-
@
|
18
|
+
def to_html
|
19
|
+
@html ||= Exporter.new(xml).to_html
|
21
20
|
end
|
22
21
|
|
23
|
-
def
|
24
|
-
|
22
|
+
def reload
|
23
|
+
@markup, @xml, @html = nil
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def parse_xml_attributes(node)
|
29
|
+
Hash[node.attributes.map { |nm, el| [nm.to_sym, el.value] }]
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_markup
|
33
|
+
segment = xml.xpath('/sheet/markup')[0]
|
34
|
+
markup = parse_xml_attributes(segment)
|
35
|
+
markup[:definitions] = begin
|
36
|
+
defines = segment.children.select { |node| node.element? }.map do |node|
|
37
|
+
attrs = parse_xml_attributes(node)
|
38
|
+
[attrs[:definition].to_sym, attrs]
|
39
|
+
end
|
40
|
+
Hash[defines]
|
41
|
+
end
|
42
|
+
markup
|
25
43
|
end
|
26
44
|
|
27
45
|
end
|
data/lib/ulysses/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ulysses
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yaodong Zhao
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -112,9 +112,10 @@ files:
|
|
112
112
|
- bin/console
|
113
113
|
- bin/setup
|
114
114
|
- lib/ulysses.rb
|
115
|
-
- lib/ulysses/exporter.rb
|
116
115
|
- lib/ulysses/group.rb
|
117
116
|
- lib/ulysses/library.rb
|
117
|
+
- lib/ulysses/printer.rb
|
118
|
+
- lib/ulysses/printer/elements.rb
|
118
119
|
- lib/ulysses/sheet.rb
|
119
120
|
- lib/ulysses/version.rb
|
120
121
|
- ulysses.gemspec
|
data/lib/ulysses/exporter.rb
DELETED
@@ -1,287 +0,0 @@
|
|
1
|
-
module Ulysses
|
2
|
-
class Exporter
|
3
|
-
|
4
|
-
def initialize(sheet_xml)
|
5
|
-
@xml = Nokogiri::XML sheet_xml
|
6
|
-
@coder = HTMLEntities.new
|
7
|
-
@annotations = []
|
8
|
-
@footnotes = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def to_html
|
12
|
-
tree = xml_to_tree @xml.xpath('/sheet/string[@xml:space="preserve"]')
|
13
|
-
html = tree_to_html tree
|
14
|
-
html = parse_prefix_tags(html)
|
15
|
-
html = append_footnotes(html)
|
16
|
-
html = append_annotations(html)
|
17
|
-
Kramdown::Document.new(html).to_html
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def xml_to_tree(xml)
|
23
|
-
xml.children.map do |child|
|
24
|
-
if child.text?
|
25
|
-
child.content
|
26
|
-
elsif child.element?
|
27
|
-
{
|
28
|
-
name: child.name,
|
29
|
-
attributes: Hash[child.attribute_nodes.map { |an| [an.node_name, an.content] }],
|
30
|
-
children: child.children.length > 0 ? xml_to_tree(child) : []
|
31
|
-
}
|
32
|
-
else
|
33
|
-
raise "Unknown node type: #{child.class}"
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def tree_to_html(tree)
|
39
|
-
html = ''
|
40
|
-
tree.each do |node|
|
41
|
-
if node.is_a?(String)
|
42
|
-
html += @coder.encode node
|
43
|
-
else
|
44
|
-
case node[:name]
|
45
|
-
when 'p'
|
46
|
-
html += p_to_html node
|
47
|
-
when 'tags'
|
48
|
-
html += tree_to_html(node[:children])
|
49
|
-
when 'tag'
|
50
|
-
html += prefix_tag_to_placeholder node
|
51
|
-
when 'element'
|
52
|
-
html += element_to_html(node)
|
53
|
-
when 'attribute'
|
54
|
-
html += attribute_to_html(node)
|
55
|
-
when 'string'
|
56
|
-
html += string_to_html(node)
|
57
|
-
else
|
58
|
-
raise "Unknown tree node type: #{node[:name]}"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
html
|
63
|
-
end
|
64
|
-
|
65
|
-
def p_to_html(node)
|
66
|
-
if node[:children].any?
|
67
|
-
tree_to_html(node[:children])
|
68
|
-
else
|
69
|
-
''
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def inline_tag_to_html(node, tag, attr = nil)
|
74
|
-
open_tag = attr.nil? ? "<#{tag} #{attr}>" : "<#{tag}>"
|
75
|
-
if node[:children].any?
|
76
|
-
open_tag + tree_to_html(node[:children]) + "</#{tag}>"
|
77
|
-
else
|
78
|
-
"#{open_tag}</#{tag}>"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def link_to_html(link)
|
83
|
-
string = '<a'
|
84
|
-
text = ''
|
85
|
-
link[:children].each do |child|
|
86
|
-
if child.is_a? String
|
87
|
-
text = child
|
88
|
-
else
|
89
|
-
identifier = child[:attributes]['identifier']
|
90
|
-
case
|
91
|
-
when 'URL'
|
92
|
-
string += ' url="'+ child[:children].first + '"'
|
93
|
-
when 'title'
|
94
|
-
string += ' title="'+ child[:children].first + '"'
|
95
|
-
else
|
96
|
-
raise "unknown link attr identifier #{identifier}"
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
string + '>' + text + '</a>'
|
101
|
-
end
|
102
|
-
|
103
|
-
def image_to_html(node)
|
104
|
-
html = '<img'
|
105
|
-
node[:children].each do |child|
|
106
|
-
case child[:attributes]['identifier']
|
107
|
-
when 'URL'
|
108
|
-
html += ' url="'+ child[:children].first + '"'
|
109
|
-
when 'title'
|
110
|
-
html += ' title="'+ child[:children].first + '"'
|
111
|
-
else
|
112
|
-
# skip
|
113
|
-
end
|
114
|
-
end
|
115
|
-
html + ' />'
|
116
|
-
end
|
117
|
-
|
118
|
-
def video_to_html(node)
|
119
|
-
source = ''
|
120
|
-
node[:children].each do |child|
|
121
|
-
case child[:attributes]['identifier']
|
122
|
-
when 'URL'
|
123
|
-
source = child[:children].first
|
124
|
-
else
|
125
|
-
# skip
|
126
|
-
end
|
127
|
-
end
|
128
|
-
'<video><source src="' + source + '"></video>'
|
129
|
-
end
|
130
|
-
|
131
|
-
def element_to_html(node)
|
132
|
-
case node[:attributes]['kind']
|
133
|
-
when 'strong'
|
134
|
-
inline_tag_to_html(node, 'strong')
|
135
|
-
when 'emph'
|
136
|
-
inline_tag_to_html(node, 'em')
|
137
|
-
when 'mark'
|
138
|
-
inline_tag_to_html(node, 'span', 'class="marked"')
|
139
|
-
when 'delete'
|
140
|
-
inline_tag_to_html(node, 'del')
|
141
|
-
when 'inlineComment'
|
142
|
-
inline_tag_to_html(node, 'span', 'class="comment"')
|
143
|
-
when 'code'
|
144
|
-
inline_tag_to_html(node, 'code')
|
145
|
-
when 'inlineNative'
|
146
|
-
inline_tag_to_html(node, 'span', 'class="native"')
|
147
|
-
when 'link'
|
148
|
-
link_to_html(node)
|
149
|
-
when 'annotation'
|
150
|
-
@annotations << [node[:children].last, tree_to_html(node[:children].first[:children])]
|
151
|
-
"<placeholder-annotation-#{@annotations.size - 1}/>"
|
152
|
-
when 'image'
|
153
|
-
image_to_html(node)
|
154
|
-
when 'video'
|
155
|
-
video_to_html(node)
|
156
|
-
when 'footnote'
|
157
|
-
string_node = node[:children].first[:children].first
|
158
|
-
@footnotes << tree_to_html(string_node[:children])
|
159
|
-
"<placeholder-footnote-#{@footnotes.size - 1}/>"
|
160
|
-
else
|
161
|
-
raise node
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def prefix_tag_to_placeholder(node)
|
166
|
-
case node[:attributes]['kind']
|
167
|
-
when 'codeblock'
|
168
|
-
string = '<<prefix-tag-code-block>>'
|
169
|
-
when 'comment'
|
170
|
-
string = '<<prefix-tag-comment>>'
|
171
|
-
when 'divider'
|
172
|
-
string = '<hr class="divider" />'
|
173
|
-
when 'nativeblock'
|
174
|
-
string = '<<prefix-tag-native-block>>'
|
175
|
-
when 'blockquote'
|
176
|
-
string = '<<prefix-tag-block-quote>>'
|
177
|
-
when 'orderedList'
|
178
|
-
string = node[:children].first
|
179
|
-
when 'unorderedList'
|
180
|
-
string = node[:children].first
|
181
|
-
when 'heading1'
|
182
|
-
string = '<<prefix-tag-heading-1>>'
|
183
|
-
when 'heading2'
|
184
|
-
string = '<<prefix-tag-heading-2>>'
|
185
|
-
when 'heading3'
|
186
|
-
string = '<<prefix-tag-heading-5>>'
|
187
|
-
when 'heading4'
|
188
|
-
string = '<<prefix-tag-heading-4>>'
|
189
|
-
when 'heading5'
|
190
|
-
string = '<<prefix-tag-heading-5>>'
|
191
|
-
when 'heading6'
|
192
|
-
string = '<<prefix-tag-heading-6>>'
|
193
|
-
else
|
194
|
-
if node[:attributes].empty? && node[:children].first == "\t"
|
195
|
-
string = "\t"
|
196
|
-
else
|
197
|
-
raise node
|
198
|
-
end
|
199
|
-
end
|
200
|
-
string
|
201
|
-
end
|
202
|
-
|
203
|
-
def attribute_to_html(node)
|
204
|
-
case node[:attributes]['identifier']
|
205
|
-
when 'text'
|
206
|
-
html = tree_to_html node[:children]
|
207
|
-
else
|
208
|
-
raise "Unknown attribute node type: #{node[:attributes]['identifier']}"
|
209
|
-
end
|
210
|
-
html
|
211
|
-
end
|
212
|
-
|
213
|
-
def string_to_html(node)
|
214
|
-
case node[:attributes]['space']
|
215
|
-
when 'preserve'
|
216
|
-
html = tree_to_html node[:children]
|
217
|
-
else
|
218
|
-
raise "Unknown string node: #{node[:attributes]['space']}"
|
219
|
-
end
|
220
|
-
html
|
221
|
-
end
|
222
|
-
|
223
|
-
def parse_prefix_tags(html)
|
224
|
-
lines = html.split("\n")
|
225
|
-
|
226
|
-
prefix_tags = []
|
227
|
-
lines = lines.map do |line|
|
228
|
-
if /\A<<(prefix-tag[a-z0-9\-]+)>>(.*)\Z/i.match line
|
229
|
-
prefix_tags << $1
|
230
|
-
"<#{$1}>" + $2 + "</#{$1}>"
|
231
|
-
else
|
232
|
-
line
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
html = lines.join("\n")
|
237
|
-
prefix_tags.uniq.each do |prefix|
|
238
|
-
case prefix
|
239
|
-
when 'prefix-tag-code-block'
|
240
|
-
html_tag = 'pre-code'
|
241
|
-
when 'prefix-tag-native-block'
|
242
|
-
html_tag = 'pre-raw'
|
243
|
-
when 'prefix-tag-comment'
|
244
|
-
html_tag = 'should-delete'
|
245
|
-
when 'prefix-tag-block-quote'
|
246
|
-
html_tag = 'blockquote'
|
247
|
-
when /\Aprefix-tag-heading-(\d)\Z/i
|
248
|
-
html_tag = "h#{$1}"
|
249
|
-
else
|
250
|
-
raise "Unknown prefix tag: #{prefix}"
|
251
|
-
end
|
252
|
-
html.gsub! %r/(<\/?)#{prefix}>/, "\\1#{html_tag}>"
|
253
|
-
html.gsub! %r/<\/#{html_tag}>(\n*)<#{html_tag}>/, "\\1"
|
254
|
-
end
|
255
|
-
|
256
|
-
html.gsub! /<should-delete>.*<\/should-delete>\n?/, ''
|
257
|
-
|
258
|
-
html.gsub! /<pre-code>/, '<pre><code>'
|
259
|
-
html.gsub! /<\/pre-code>/, '</code></pre>'
|
260
|
-
|
261
|
-
html.gsub! /<pre-raw>/, '<p class="raw">'
|
262
|
-
html.gsub! /<\/pre-raw>/, '</p>'
|
263
|
-
|
264
|
-
html
|
265
|
-
end
|
266
|
-
|
267
|
-
def append_footnotes(html)
|
268
|
-
footnote_html = '<div class="footnotes">'
|
269
|
-
@footnotes.each_with_index do |fn, index|
|
270
|
-
html.gsub! /<placeholder-footnote-#{index}\/>/, "<sup><a href=\"#fn#{index}\" id=\"ref#{index}\">#{index}</a></sup>"
|
271
|
-
footnote_html += "<sup id=\"fn#{index}\">#{index}. " + fn + '</sup>'
|
272
|
-
end
|
273
|
-
html + "\n\n" + footnote_html + "</div>\n"
|
274
|
-
end
|
275
|
-
|
276
|
-
def append_annotations(html)
|
277
|
-
annotations_html = '<div class="annotations">'
|
278
|
-
@annotations.each_with_index do |at, index|
|
279
|
-
html.gsub! /<placeholder-annotation-#{index}/, "<span class=\"annotated\" data-annotation=\"#{index}\">#{at[0]}</span>"
|
280
|
-
annotations_html += "<section data-annotation=\"#{index}\">" + at[1] + '</section>'
|
281
|
-
end
|
282
|
-
|
283
|
-
html + "\n\n" + annotations_html + "</div>\n"
|
284
|
-
end
|
285
|
-
|
286
|
-
end
|
287
|
-
end
|