ppz 0.0.0 → 0.0.1
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/bin/ppz-util.rb +31 -0
- data/lib/func/util.rb +12 -0
- data/lib/object/model/abstract/model.rb +44 -0
- data/lib/object/model/abstract/wrapper-model.rb +21 -0
- data/lib/object/model/common/escape.rb +34 -0
- data/lib/object/model/common/tag.rb +15 -0
- data/lib/object/model/common/tag.test.rb +25 -0
- data/lib/object/model/list/item/abstract.rb +15 -0
- data/lib/object/model/list/item/unordered.rb +5 -0
- data/lib/object/model/list/wrapper/abstract.rb +7 -0
- data/lib/object/model/list/wrapper/unordered.rb +5 -0
- data/lib/object/model/p/index.rb +15 -0
- data/lib/object/model/section/abstract.rb +10 -0
- data/lib/object/model/section/leaf.rb +35 -0
- data/lib/object/model/section/root.rb +7 -0
- data/lib/object/model/section/test.rb +12 -0
- data/lib/object/model/special-block/container.rb +18 -0
- data/lib/object/model/special-block/item.rb +10 -0
- data/lib/object/parser/common/context/abstract.rb +32 -0
- data/lib/object/parser/common/context/doc.rb +15 -0
- data/lib/object/parser/doc/abstract.rb +69 -0
- data/lib/object/parser/doc/file.rb +24 -0
- data/lib/object/parser/doc/file.test.rb +6 -0
- data/lib/object/parser/doc/string.rb +12 -0
- data/lib/object/parser/folder/index.rb +7 -0
- metadata +27 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6ecf116f7998efdb6f554563f6b5e9c447872cc3c8d4531fbdba899b986bfcf
|
|
4
|
+
data.tar.gz: 545155a99ebdca8a31cd3ec012c2e6a7971a379bd9b97eba7d867c755930a377
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5743fdd2c32cca4a9a0e5a67859de962af84252cc1bbceac2a697a724bf49ea8941951824bb504e112d6788b29ba21cd6fa3713a2ec49fe0c4ae565a326968c2
|
|
7
|
+
data.tar.gz: 3ec750c9c3580309128c5057e787523933997b3a1108e653b4ce6fbf3222c976772ba9e5439856e3b78ddb2703f6a75e06facf04504befffdcc49be47210ad21
|
data/bin/ppz-util.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require 'pathname'
|
|
2
|
+
|
|
3
|
+
class UtilInMain
|
|
4
|
+
class << self
|
|
5
|
+
def get_file_in_and_out
|
|
6
|
+
file_in, file_out = ARGV
|
|
7
|
+
unless file_in && file_out
|
|
8
|
+
abort '参数不对啊,需要至少俩参数(输入文件路径、输出文件路径)'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
current_path = Pathname Dir.pwd
|
|
12
|
+
file_in = (current_path + file_in).to_s
|
|
13
|
+
file_out = (current_path + file_out).to_s
|
|
14
|
+
|
|
15
|
+
unless File.exist? file_in
|
|
16
|
+
abort '没有 ' + file_in + " 这个文件\n【参数不正确:ppz 源文件不存在】"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
file_out_dir = File.dirname file_out
|
|
20
|
+
unless Dir.exist? file_out_dir
|
|
21
|
+
abort '输出文件的目录不存在'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
if File.exist? file_out
|
|
25
|
+
abort '输出文件已存在'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
[file_in, file_out]
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/func/util.rb
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require_relative '../common/escape'
|
|
2
|
+
|
|
3
|
+
class AbstractModel
|
|
4
|
+
def self.from_line line # 静态方法,从“输入行”里实例化一个 model
|
|
5
|
+
if match_data = self::REG_EXP.match(line)
|
|
6
|
+
self.new match_data.post_match
|
|
7
|
+
else
|
|
8
|
+
nil
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# 加粗、斜体、链接等
|
|
13
|
+
def transform_inline_element str
|
|
14
|
+
str = str + ''
|
|
15
|
+
# 因为加粗、斜体等,会生成 html 代码,为了不使“用户原本输入的 html”和“生成的 html”冲突,因此先把“用户输入的 html 转义
|
|
16
|
+
Escape.html_char! str
|
|
17
|
+
|
|
18
|
+
# 变粗等,使用特殊字符比如 *,来标识
|
|
19
|
+
# 但这会使用户想输入 * 时,形成歧义
|
|
20
|
+
# 因此,用户向输入 *(而不是变斜时),可以输入 \*
|
|
21
|
+
|
|
22
|
+
# 所以此流程
|
|
23
|
+
# 先把 * 等特殊字符转义(\* -> 某种形式)
|
|
24
|
+
# 再识别哪些变斜,哪些变粗
|
|
25
|
+
# 再把用户原来想输入的 * 放到字符串里(某种形式 -> *)
|
|
26
|
+
|
|
27
|
+
Escape.ppz_char! str # 把用户输入的 \* 转义 => 剩下的 *** 就肯定是 斜体加粗 了
|
|
28
|
+
|
|
29
|
+
# 1. 斜体和加粗
|
|
30
|
+
str.gsub! /\*\*\*(.+)\*\*\*/, '<b><i>\1</i></b>'
|
|
31
|
+
# 2. 加粗
|
|
32
|
+
str.gsub! /\*\*(.+)\*\*/, '<b>\1</b>'
|
|
33
|
+
# 3. 斜体
|
|
34
|
+
str.gsub! /\*(.+)\*/, '<i>\1</i>'
|
|
35
|
+
# 4. 行内块
|
|
36
|
+
str.gsub! /```(.+)```/, '<span class="special-txt">\1</span>'
|
|
37
|
+
# 5. 链接
|
|
38
|
+
str.gsub! /\[([^\]]+)\]\(([^\)]+)\)/, '<a href="\2" title="\2">\1</a>'
|
|
39
|
+
# 6. 图片
|
|
40
|
+
str.gsub! /!\[([^\]]*)\]\(([^\)]+)\)/, '<img title="\1" src="\2" />'
|
|
41
|
+
|
|
42
|
+
Escape.transform_to_real! str
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require_relative './model'
|
|
2
|
+
|
|
3
|
+
class AbstractWrapperModel < AbstractModel
|
|
4
|
+
def initialize
|
|
5
|
+
@children = []
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# 把 el 加入到 children
|
|
9
|
+
def append el
|
|
10
|
+
if el.respond_to? :on_append
|
|
11
|
+
el.on_append
|
|
12
|
+
end
|
|
13
|
+
@children.push el
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def to_html
|
|
17
|
+
@children
|
|
18
|
+
.map { |child| child.to_html }
|
|
19
|
+
.join
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class Escape
|
|
2
|
+
PpzRule = [
|
|
3
|
+
['\\\\', '\\backslash', '\\'],
|
|
4
|
+
['\\*', '\\star;', '*'],
|
|
5
|
+
['\\`', '\\backquote;', '`']
|
|
6
|
+
]
|
|
7
|
+
class << self
|
|
8
|
+
def ppz_char! str
|
|
9
|
+
PpzRule.each do |source, escaped|
|
|
10
|
+
str.gsub! source, escaped
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def transform_to_real! str
|
|
15
|
+
PpzRule.each do |source, escaped, target|
|
|
16
|
+
str.gsub! escaped, target
|
|
17
|
+
end
|
|
18
|
+
str
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
HtmlRule = [
|
|
23
|
+
['&', '&'],
|
|
24
|
+
['<', '<'],
|
|
25
|
+
['>', '>'],
|
|
26
|
+
[' ', ' '],
|
|
27
|
+
['"', '"']
|
|
28
|
+
]
|
|
29
|
+
def self.html_char! str
|
|
30
|
+
HtmlRule.each do |source, escaped|
|
|
31
|
+
str.gsub! source, escaped
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Tag
|
|
2
|
+
def initialize name, content, attr
|
|
3
|
+
@tagName = tagName
|
|
4
|
+
@content = content
|
|
5
|
+
@attr = attr
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def to_s
|
|
9
|
+
attrStr = ''
|
|
10
|
+
@attr.each do |key, value|
|
|
11
|
+
attrStr << " #{key}='#{value}'"
|
|
12
|
+
end
|
|
13
|
+
"<#{@tagName}#{attrStr}>#{@content}</#{@tagName}>"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require_relative './tag'
|
|
2
|
+
require_relative 'test/unit'
|
|
3
|
+
|
|
4
|
+
class TagTest < Test::Unit::TestCase
|
|
5
|
+
def test_1
|
|
6
|
+
assert_equal '<div></div>', AbstractModel.new.getTag
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_2
|
|
10
|
+
assert_equal '<div>ha i</div>', AbstractModel.new('ha i').getTag
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def test_3
|
|
14
|
+
assert_equal '<span>hai</span>', AbstractModel.new('hai', tagName: 'span').getTag
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_4
|
|
18
|
+
assert_equal '<span name=\'test\' tel=\'110\'>hai</span>', AbstractModel.new('hai', tagName: 'span',
|
|
19
|
+
attr: {
|
|
20
|
+
name: 'test',
|
|
21
|
+
tel: '110'
|
|
22
|
+
}
|
|
23
|
+
).getTag
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require_relative '../../abstract/wrapper-model'
|
|
2
|
+
|
|
3
|
+
class AbstractListItemModel < AbstractModel
|
|
4
|
+
def initialize text
|
|
5
|
+
@text = transform_inline_element text
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def on_append
|
|
9
|
+
puts '+: ' + @text
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def to_html
|
|
13
|
+
"<li>#{@text}</li>"
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative './abstract'
|
|
2
|
+
|
|
3
|
+
class LeafSectionModel < AbstractSectionModel
|
|
4
|
+
|
|
5
|
+
attr_accessor :title, :father
|
|
6
|
+
attr_reader :level
|
|
7
|
+
|
|
8
|
+
def initialize title, level
|
|
9
|
+
raise TypeError unless title.is_a?(String) && level.is_a?(Integer)
|
|
10
|
+
super() # 不可以省略括号
|
|
11
|
+
@title = transform_inline_element title
|
|
12
|
+
@level = level
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
REG_EXP = /^\#{1,5} /
|
|
16
|
+
def self.from_line line
|
|
17
|
+
return nil unless match_data = REG_EXP.match(line)
|
|
18
|
+
|
|
19
|
+
level = {
|
|
20
|
+
2 => 1,
|
|
21
|
+
6 => 3
|
|
22
|
+
}[match_data.to_s.length] || 2
|
|
23
|
+
LeafSectionModel.new match_data.post_match, level
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def on_append
|
|
27
|
+
puts 'h: ' + @title
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def to_html
|
|
31
|
+
%{<section><h#{@level}>#{@title}</h#{@level}>#{
|
|
32
|
+
super
|
|
33
|
+
}</section>}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
require_relative './leaf'
|
|
3
|
+
require_relative './root'
|
|
4
|
+
|
|
5
|
+
root = RootSectionModel.new
|
|
6
|
+
leaf1 = LeafSectionModel.new '一级标题'
|
|
7
|
+
leaf2 = LeafSectionModel.new '第二个一级标题'
|
|
8
|
+
leaf11 = LeafSectionModel.new '二级标题'
|
|
9
|
+
|
|
10
|
+
root.append leaf1
|
|
11
|
+
leaf1.append leaf11
|
|
12
|
+
root.append leaf2
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative '../abstract/wrapper-model'
|
|
2
|
+
|
|
3
|
+
class SpecialContainerModel < AbstractWrapperModel
|
|
4
|
+
REG_EXP = /^``` (.+)/
|
|
5
|
+
def self.from_line line
|
|
6
|
+
return nil unless match_data = REG_EXP.match(line)
|
|
7
|
+
SpecialContainerModel.new $1
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize name
|
|
11
|
+
@name = name
|
|
12
|
+
super()
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_html
|
|
16
|
+
"<div class=\"special-block #{@name}\">#{super}</div>"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 当前行,所处的上下文
|
|
2
|
+
# 比如 一级 section 下面的 ul 下的 第 n 个 ul
|
|
3
|
+
|
|
4
|
+
class AbstractContext
|
|
5
|
+
def initialize root
|
|
6
|
+
@stack = [root]
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def append target
|
|
10
|
+
@stack.push target
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pop
|
|
14
|
+
@stack.pop
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def head
|
|
18
|
+
@stack[-1]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def root
|
|
22
|
+
@stack[0]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
def pop_to klass
|
|
27
|
+
loop do
|
|
28
|
+
break if head.is_a? klass
|
|
29
|
+
pop
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require_relative '../../../model/section/abstract'
|
|
2
|
+
require_relative './abstract'
|
|
3
|
+
|
|
4
|
+
class DocContext < AbstractContext
|
|
5
|
+
def level
|
|
6
|
+
@stack.reverse_each do |item|
|
|
7
|
+
return item.level if item.is_a? AbstractSectionModel
|
|
8
|
+
end
|
|
9
|
+
throw '不应该到这里'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def pop_to_section
|
|
13
|
+
pop_to AbstractSectionModel
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# 解析一个 .ppz 文档(可以是一个文件、字符串)
|
|
2
|
+
|
|
3
|
+
require_relative '../common/context/doc'
|
|
4
|
+
require_relative '../../model/section/leaf'
|
|
5
|
+
require_relative '../../model/section/root'
|
|
6
|
+
require_relative '../../model/p/index'
|
|
7
|
+
require_relative '../../model/list/item/unordered'
|
|
8
|
+
require_relative '../../model/list/wrapper/unordered'
|
|
9
|
+
require_relative '../../model/special-block/container'
|
|
10
|
+
require_relative '../../model/special-block/item'
|
|
11
|
+
|
|
12
|
+
class AbstractDocParser
|
|
13
|
+
def initialize
|
|
14
|
+
@context = DocContext.new RootSectionModel.new
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def get_model
|
|
18
|
+
loop do
|
|
19
|
+
line = readline
|
|
20
|
+
break unless line != nil
|
|
21
|
+
handle_line line
|
|
22
|
+
end
|
|
23
|
+
@context.root
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
def handle_line line
|
|
28
|
+
if @context.head.is_a? SpecialContainerModel
|
|
29
|
+
# special-block
|
|
30
|
+
if /^``` *$/.match line
|
|
31
|
+
# special-block-end
|
|
32
|
+
@context.pop
|
|
33
|
+
return
|
|
34
|
+
else
|
|
35
|
+
# special-block-item
|
|
36
|
+
target = SpecialItemModel.new line
|
|
37
|
+
end
|
|
38
|
+
elsif target = SpecialContainerModel.from_line(line)
|
|
39
|
+
# special-block-container
|
|
40
|
+
elsif target = LeafSectionModel.from_line(line)
|
|
41
|
+
# section
|
|
42
|
+
# 检查 level
|
|
43
|
+
loop do
|
|
44
|
+
break if @context.level < target.level
|
|
45
|
+
@context.pop
|
|
46
|
+
end
|
|
47
|
+
elsif target = UnorderedListItemModel.from_line(line)
|
|
48
|
+
# 列表
|
|
49
|
+
unless @context.head.is_a? UnorderedListWrapperModel # 如果当前不在一个 无序列表 里
|
|
50
|
+
wrapper = UnorderedListWrapperModel.new # 就整一个无序列表
|
|
51
|
+
@context.pop_to_section # 找到最近的 section
|
|
52
|
+
@context.head.append wrapper # 加入 wrapper
|
|
53
|
+
@context.append wrapper # wrapper 入上下文栈
|
|
54
|
+
end
|
|
55
|
+
# p
|
|
56
|
+
else
|
|
57
|
+
@context.pop_to_section # 找到最近的 section
|
|
58
|
+
target = PModel.new line
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# 添加到父级 model
|
|
62
|
+
@context.head.append target
|
|
63
|
+
|
|
64
|
+
# 推入上下文
|
|
65
|
+
if target.is_a? AbstractWrapperModel
|
|
66
|
+
@context.append target
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require_relative './abstract'
|
|
2
|
+
|
|
3
|
+
class FileDocParser < AbstractDocParser
|
|
4
|
+
def initialize path
|
|
5
|
+
super()
|
|
6
|
+
unless File.exist? path
|
|
7
|
+
throw '文件不存在,可能是路径错了(需要绝对路径):' + path
|
|
8
|
+
end
|
|
9
|
+
@file = File.new path
|
|
10
|
+
@end = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private def readline
|
|
14
|
+
return nil if @end
|
|
15
|
+
|
|
16
|
+
begin
|
|
17
|
+
line = @file.readline
|
|
18
|
+
return line[-1] == '\n'? line[0...-1] : line
|
|
19
|
+
rescue EOFError => err
|
|
20
|
+
@end = true
|
|
21
|
+
return nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ppz
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- wuse
|
|
@@ -10,7 +10,7 @@ bindir: bin
|
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 2021-02-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description:
|
|
13
|
+
description:
|
|
14
14
|
email: 372301467@qq.com
|
|
15
15
|
executables:
|
|
16
16
|
- ppz
|
|
@@ -18,6 +18,31 @@ extensions: []
|
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
20
|
- bin/ppz
|
|
21
|
+
- bin/ppz-util.rb
|
|
22
|
+
- lib/func/util.rb
|
|
23
|
+
- lib/object/model/abstract/model.rb
|
|
24
|
+
- lib/object/model/abstract/wrapper-model.rb
|
|
25
|
+
- lib/object/model/common/escape.rb
|
|
26
|
+
- lib/object/model/common/tag.rb
|
|
27
|
+
- lib/object/model/common/tag.test.rb
|
|
28
|
+
- lib/object/model/list/item/abstract.rb
|
|
29
|
+
- lib/object/model/list/item/unordered.rb
|
|
30
|
+
- lib/object/model/list/wrapper/abstract.rb
|
|
31
|
+
- lib/object/model/list/wrapper/unordered.rb
|
|
32
|
+
- lib/object/model/p/index.rb
|
|
33
|
+
- lib/object/model/section/abstract.rb
|
|
34
|
+
- lib/object/model/section/leaf.rb
|
|
35
|
+
- lib/object/model/section/root.rb
|
|
36
|
+
- lib/object/model/section/test.rb
|
|
37
|
+
- lib/object/model/special-block/container.rb
|
|
38
|
+
- lib/object/model/special-block/item.rb
|
|
39
|
+
- lib/object/parser/common/context/abstract.rb
|
|
40
|
+
- lib/object/parser/common/context/doc.rb
|
|
41
|
+
- lib/object/parser/doc/abstract.rb
|
|
42
|
+
- lib/object/parser/doc/file.rb
|
|
43
|
+
- lib/object/parser/doc/file.test.rb
|
|
44
|
+
- lib/object/parser/doc/string.rb
|
|
45
|
+
- lib/object/parser/folder/index.rb
|
|
21
46
|
- lib/ppz.rb
|
|
22
47
|
homepage: https://github.com/daGaiGuanYu/ppz
|
|
23
48
|
licenses:
|