ulysses 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Join the chat at https://gitter.im/yaodong/gem-ulysses](https://badges.gitter.im/yaodong/gem-ulysses.svg)](https://gitter.im/yaodong/gem-ulysses?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Code Climate](https://codeclimate.com/github/yaodong/gem-ulysses/badges/gpa.svg)](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
|