This repository has been archived by the owner on Feb 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
hikidoc_pre.rb
151 lines (141 loc) · 4.59 KB
/
hikidoc_pre.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
## parse from '<<<' to '>>>'
##
## ex. preformatted text
## <<<
## x: foo
## y: bar
## >>>
##
## result:
## <pre>
## x: foo
## y: bar
## </pre>
##
## ex. preformatted text with line numbers, inline marking, and class attribute
## <<<: linenum=5, inline=true, class=console, format='%03d| '
## x: {{*foo*}}
## y: {{/bar/}}
## >>>
##
## result:
## <div style="text-align:right">
## <a onclick="javascript:toggle_linenums(this)">hide line numbers</a>
## </div>
## <pre class="console">
## <span>005|</span> x: <strong>foo</strong>
## <span>006|</span> y: <em>bar</em>
## </pre>
##
## If 'linenum' option is specified, '<a>hide line numbers</a>' is placed
## which can hide/show line numbers.
##
## Several short notations are provided.
## * '<<<#' is equivarent to '<<<: linenum=1'
## * '<<<*' is equivarent to '<<<: inline=true'
## * '<<<%' is equivarent to '<<<: class=console'
## * '<<<#*%' is equivarent to '<<<: linenum=1, inline=true, class=console'
## (order of '#', '*', and '%' is not important)
## * '<<<#*: class=name' is also available
##
## Default format is '%03d: '.
##
require 'hikidoc'
class ::HikiDoc
def parse_pre( text )
ret = text
ret.gsub!( /^#{MULTI_PRE_OPEN_RE}([#*%]*)(?::[ \t]+(.*?))?$(.*?)^#{MULTI_PRE_CLOSE_RE}$/m ) do |str|
opts = _parse_options($2)
content = restore_pre($3)
content = _manipulate_pre_content(content, opts, $1)
prefix = _toggle_linenums_anchor(opts, $1)
stag, etag = _create_pre_tags(opts, $1)
"\n" + prefix + store_block( "#{stag}#{content}#{etag}" ) + "\n\n"
end
ret.gsub!( /(?:#{PRE_RE}.*\n?)+/ ) do |str|
str.chomp!
str.gsub!( PRE_RE, '' )
"\n" + store_block( "<pre>\n#{restore_pre(str)}\n</pre>" ) + "\n\n"
end
ret
end
def _toggle_linenums_script()
return <<END
<script language="javascript" type="text/javascript">
<!--
;function toggle_linenum(elem_anchor) {
; var label = elem_anchor.firstChild.nodeValue;
; var action = label.substring(0, 4) == 'show' ? 'hide' : 'show';
; elem_anchor.firstChild.nodeValue = action + ' line numbers';
; var display = action == 'show' ? 'none' : 'inline';
; var elem_pre = elem_anchor.parentNode.nextSibling;
; for (var i = 0, n = elem_pre.childNodes.length; i < n; i++) {
; var child = elem_pre.childNodes[i];
; if (child.tagName == 'SPAN') {
; child.style.display = display;
; }
; }
;}
-->
</script>
END
end
def _toggle_linenums_anchor(opts, optstr)
flag_linenum = opts.fetch('linenum', optstr.include?('#') ? 1 : nil).is_a?(Integer)
return '' unless flag_linenum
anchor = '<div style="text-align:right;margin-bottom:-2em;font-size:small;"><a onclick="javascript:toggle_linenum(this);return false">hide line numbers</a></div>'
return anchor if @_toggle_linenums
@_toggle_linenums = true
script = _toggle_linenums_script()
return script + anchor
end
def _create_pre_tags(opts, optstr)
class_attr = opts.fetch('class', optstr.include?('%') ? 'console' : nil)
attr = class_attr ? " class=\"#{escape_quote(class_attr)}\"" : ""
return "<pre#{attr}>", "</pre>"
end
# LINENUMS_DEFAULT_FORMAT = '%3d: '
def _manipulate_pre_content(content, opts, optstr)
optstr ||= ''
linenum = opts.fetch('linenum', optstr.include?('#') ? 1 : nil)
inline = opts.fetch('inline', optstr.include?('*'))
# add line numbers
if linenum.is_a?(Integer)
n = linenum - 1
# format = opts.fetch('format', LINENUMS_DEFAULT_FORMAT)
format = opts.fetch('format', '%3d: ')
content.gsub!(/\A\r?\n/, '')
content.gsub!(/^/) { "<span>#{format % (n += 1)}</span>" }
content = "\n" + content
end
# {{*text*}} => <strong>text</strong>, {{/text/}} => <em>text</em>
if inline == true
content.gsub!(/\{\{\*(.*?)\*\}\}/, '<strong>\1</strong>')
content.gsub!(/\{\{\/(.*?)\/\}\}/, '<em>\1</em>')
content.gsub!(/\{\{\}\}/, '')
end
return content
end
def _parse_options(option_str)
opts = {}
option_str.split(/\s*,\s*/).each do |option|
if option =~ /\A(\w+)(?:=(.*))?/
key, val = $1, $2
case val
when nil ; val = true
when 'true', 'yes' ; val = true
when 'false', 'no' ; val = false
when 'nil', 'null' ; val = nil
when /\A[-+]?\d+\z/ ; val = val.to_i
when /\A[-+]?\d+\.\d+\z/ ; val = val.to_f
when /\A'(.*)'\z/ ; val = $1
when /\A"(.*)"\z/ ; val = $1
end
else
key, val = option, true
end
opts[key.strip] = val
end if option_str
return opts
end
end