ppz 0.0.3 → 0.0.4
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/asset/style/ppz.css +90 -90
- data/bin/common.rb +9 -10
- data/bin/doc.rb +17 -0
- data/bin/folder.rb +10 -0
- data/bin/ppz +6 -10
- data/lib/func/util.rb +9 -1
- data/lib/parser/folder/index.rb +12 -4
- data/lib/parser/folder/model/abstract.rb +27 -0
- data/lib/parser/folder/model/file/abstract.rb +23 -0
- data/lib/parser/folder/model/file/other.rb +7 -0
- data/lib/parser/folder/model/file/ppz.rb +10 -0
- data/lib/parser/folder/model/folder.rb +51 -0
- metadata +9 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3b73ebb97359023698601b83e6e081bc37860d7a0e698dfe42bdfc4e00b6c0b6
|
|
4
|
+
data.tar.gz: 47d3ffb5a9d3e5aa6a4e5b6e48e6d1f36dfec625fc067014c712ce15914fd0d0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7f22341cf785fbe0becad3d299d2a9abd3b1c939489b37fca2f5e5120545178d6e1510e0d40b458b825a0f5b0eb8d15f82c5cd9902b8b84570556b478a89b676
|
|
7
|
+
data.tar.gz: 891541f4789e74d18f9847b133f59e4ad1f0c171be6a11b7e070caba65f08f03adf9cbe41a3c3047ec563081153f8d2ae92f4f38215d3253e38d43a0b31f6757
|
data/asset/style/ppz.css
CHANGED
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
html {
|
|
2
|
-
line-height: 1.5;
|
|
3
|
-
}
|
|
4
|
-
body,
|
|
5
|
-
div,
|
|
6
|
-
p,
|
|
7
|
-
aside {
|
|
8
|
-
box-sizing: border-box;
|
|
9
|
-
}
|
|
10
|
-
body {
|
|
11
|
-
margin: 0;
|
|
12
|
-
padding: 0;
|
|
13
|
-
position: relative;
|
|
14
|
-
}
|
|
15
|
-
aside {
|
|
16
|
-
overflow-y: auto;
|
|
17
|
-
padding: 2rem 1rem;
|
|
18
|
-
position: fixed;
|
|
19
|
-
top: 0;
|
|
20
|
-
left: 0;
|
|
21
|
-
width: 188px;
|
|
22
|
-
height: 100vh;
|
|
23
|
-
}
|
|
24
|
-
aside ul {
|
|
25
|
-
margin: 0 0 0 1rem;
|
|
26
|
-
padding: 0;
|
|
27
|
-
list-style: none;
|
|
28
|
-
}
|
|
29
|
-
aside a {
|
|
30
|
-
width: 100%;
|
|
31
|
-
overflow: hidden;
|
|
32
|
-
text-overflow: ellipsis;
|
|
33
|
-
white-space: nowrap;
|
|
34
|
-
}
|
|
35
|
-
article {
|
|
36
|
-
margin-left: 188px;
|
|
37
|
-
padding: 1px 1rem;
|
|
38
|
-
}
|
|
39
|
-
h1 {
|
|
40
|
-
font-size: 2rem;
|
|
41
|
-
}
|
|
42
|
-
h2 {
|
|
43
|
-
font-size: 1.3rem;
|
|
44
|
-
}
|
|
45
|
-
h3 {
|
|
46
|
-
font-size: 1.1rem;
|
|
47
|
-
opacity: 0.9;
|
|
48
|
-
}
|
|
49
|
-
h1::before,
|
|
50
|
-
h2::before,
|
|
51
|
-
h3::before {
|
|
52
|
-
content: '# ';
|
|
53
|
-
opacity: 0.3;
|
|
54
|
-
font-size: 1rem;
|
|
55
|
-
}
|
|
56
|
-
.comment-container {
|
|
57
|
-
margin: 1rem 0;
|
|
58
|
-
padding: 1rem 1.6rem;
|
|
59
|
-
background: rgba(0,0,0,0.2);
|
|
60
|
-
font-size: 0.9rem;
|
|
61
|
-
border-radius: 4px;
|
|
62
|
-
}
|
|
63
|
-
.comment-item {
|
|
64
|
-
opacity: 0.8;
|
|
65
|
-
}
|
|
66
|
-
.special-block-container {
|
|
67
|
-
background: #141c22;
|
|
68
|
-
overflow: auto;
|
|
69
|
-
border-radius: 4px;
|
|
70
|
-
color: #eee;
|
|
71
|
-
font-family: monospace;
|
|
72
|
-
white-space: pre;
|
|
73
|
-
margin: 1rem 0;
|
|
74
|
-
padding: 1rem;
|
|
75
|
-
counter-reset: line-index;
|
|
76
|
-
}
|
|
77
|
-
.special-block-item::before {
|
|
78
|
-
counter-increment: line-index;
|
|
79
|
-
content: counter(line-index) " | ";
|
|
80
|
-
opacity: 0.3;
|
|
81
|
-
}
|
|
82
|
-
.special-block-item:hover::before {
|
|
83
|
-
opacity: 0.8;
|
|
84
|
-
}
|
|
85
|
-
.special-txt {
|
|
86
|
-
background: rgba(27,31,35,0.05);
|
|
87
|
-
border-radius: 4px;
|
|
88
|
-
font-size: 0.9em;
|
|
89
|
-
padding: 2px 4px;
|
|
90
|
-
}
|
|
1
|
+
html {
|
|
2
|
+
line-height: 1.5;
|
|
3
|
+
}
|
|
4
|
+
body,
|
|
5
|
+
div,
|
|
6
|
+
p,
|
|
7
|
+
aside {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
}
|
|
10
|
+
body {
|
|
11
|
+
margin: 0;
|
|
12
|
+
padding: 0;
|
|
13
|
+
position: relative;
|
|
14
|
+
}
|
|
15
|
+
aside {
|
|
16
|
+
overflow-y: auto;
|
|
17
|
+
padding: 2rem 1rem;
|
|
18
|
+
position: fixed;
|
|
19
|
+
top: 0;
|
|
20
|
+
left: 0;
|
|
21
|
+
width: 188px;
|
|
22
|
+
height: 100vh;
|
|
23
|
+
}
|
|
24
|
+
aside ul {
|
|
25
|
+
margin: 0 0 0 1rem;
|
|
26
|
+
padding: 0;
|
|
27
|
+
list-style: none;
|
|
28
|
+
}
|
|
29
|
+
aside a {
|
|
30
|
+
width: 100%;
|
|
31
|
+
overflow: hidden;
|
|
32
|
+
text-overflow: ellipsis;
|
|
33
|
+
white-space: nowrap;
|
|
34
|
+
}
|
|
35
|
+
article {
|
|
36
|
+
margin-left: 188px;
|
|
37
|
+
padding: 1px 1rem;
|
|
38
|
+
}
|
|
39
|
+
h1 {
|
|
40
|
+
font-size: 2rem;
|
|
41
|
+
}
|
|
42
|
+
h2 {
|
|
43
|
+
font-size: 1.3rem;
|
|
44
|
+
}
|
|
45
|
+
h3 {
|
|
46
|
+
font-size: 1.1rem;
|
|
47
|
+
opacity: 0.9;
|
|
48
|
+
}
|
|
49
|
+
h1::before,
|
|
50
|
+
h2::before,
|
|
51
|
+
h3::before {
|
|
52
|
+
content: '# ';
|
|
53
|
+
opacity: 0.3;
|
|
54
|
+
font-size: 1rem;
|
|
55
|
+
}
|
|
56
|
+
.comment-container {
|
|
57
|
+
margin: 1rem 0;
|
|
58
|
+
padding: 1rem 1.6rem;
|
|
59
|
+
background: rgba(0,0,0,0.2);
|
|
60
|
+
font-size: 0.9rem;
|
|
61
|
+
border-radius: 4px;
|
|
62
|
+
}
|
|
63
|
+
.comment-item {
|
|
64
|
+
opacity: 0.8;
|
|
65
|
+
}
|
|
66
|
+
.special-block-container {
|
|
67
|
+
background: #141c22;
|
|
68
|
+
overflow: auto;
|
|
69
|
+
border-radius: 4px;
|
|
70
|
+
color: #eee;
|
|
71
|
+
font-family: monospace;
|
|
72
|
+
white-space: pre;
|
|
73
|
+
margin: 1rem 0;
|
|
74
|
+
padding: 1rem;
|
|
75
|
+
counter-reset: line-index;
|
|
76
|
+
}
|
|
77
|
+
.special-block-item::before {
|
|
78
|
+
counter-increment: line-index;
|
|
79
|
+
content: counter(line-index) " | ";
|
|
80
|
+
opacity: 0.3;
|
|
81
|
+
}
|
|
82
|
+
.special-block-item:hover::before {
|
|
83
|
+
opacity: 0.8;
|
|
84
|
+
}
|
|
85
|
+
.special-txt {
|
|
86
|
+
background: rgba(27,31,35,0.05);
|
|
87
|
+
border-radius: 4px;
|
|
88
|
+
font-size: 0.9em;
|
|
89
|
+
padding: 2px 4px;
|
|
90
|
+
}
|
data/bin/common.rb
CHANGED
|
@@ -2,7 +2,6 @@ require 'pathname'
|
|
|
2
2
|
|
|
3
3
|
module PPZMain
|
|
4
4
|
CURRENT_PATH = File.dirname __FILE__
|
|
5
|
-
WORK_DIRECTORY = Pathname Dir.pwd
|
|
6
5
|
CSS_FILE_PATH = (Pathname CURRENT_PATH) + '../asset/style/ppz.css'
|
|
7
6
|
|
|
8
7
|
class Util
|
|
@@ -10,33 +9,33 @@ module PPZMain
|
|
|
10
9
|
def get_in_and_out
|
|
11
10
|
target_in, target_out = ARGV
|
|
12
11
|
|
|
13
|
-
#
|
|
12
|
+
# 输入文件
|
|
14
13
|
abort '要编译哪那个文件?请告诉我' unless target_in # 检查参数存在
|
|
15
|
-
target_in =
|
|
14
|
+
target_in = PPZ::Func.format_path target_in
|
|
16
15
|
unless File.exist? target_in # 不存在的话,看看加上 .ppz 后是否存在
|
|
17
16
|
target_in += '.ppz'
|
|
18
17
|
abort target_in[0..-5] + ' 不存在' unless File.exist? target_in # 还不存在的话,就说明是写错了
|
|
19
18
|
end
|
|
20
|
-
|
|
19
|
+
is_folder = File.directory? target_in
|
|
21
20
|
|
|
22
|
-
#
|
|
21
|
+
# 输出文件
|
|
23
22
|
unless target_out
|
|
24
23
|
# 从输入文件获取文件名
|
|
25
24
|
target_out = ((/(.*).ppz$/.match target_in)?$1:target_in) + '.pp'
|
|
26
25
|
end
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
upper_dir = (target_out + '..').to_s
|
|
26
|
+
# + 检查上级文件夹是否存在
|
|
27
|
+
upper_dir = ((Pathname target_out) + '..').to_s
|
|
30
28
|
abort upper_dir + ' 目录不存在' unless Dir.exist? upper_dir
|
|
31
|
-
#
|
|
29
|
+
# + 检查文件夹:有则检查里面有没有文件;无则创建文件夹
|
|
32
30
|
target_out = target_out.to_s
|
|
33
31
|
if Dir.exist? target_out
|
|
34
32
|
abort target_out + ' 不是一个空文件夹' unless (Dir.children target_out).size == 0
|
|
35
33
|
else
|
|
36
34
|
Dir.mkdir target_out
|
|
37
35
|
end
|
|
36
|
+
target_out = PPZ::Func.format_path target_out
|
|
38
37
|
|
|
39
|
-
[target_in, target_out]
|
|
38
|
+
[target_in, target_out, is_folder]
|
|
40
39
|
end
|
|
41
40
|
end
|
|
42
41
|
end
|
data/bin/doc.rb
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
target_out = Pathname TARGET_OUT
|
|
2
|
+
|
|
3
|
+
# css
|
|
4
|
+
# 输出文件路径
|
|
5
|
+
output_css_path = target_out + 'index.css'
|
|
6
|
+
# 复制
|
|
7
|
+
FileUtils.cp PPZMain::CSS_FILE_PATH, output_css_path
|
|
8
|
+
|
|
9
|
+
# html
|
|
10
|
+
# 输出文件路径
|
|
11
|
+
output_html_path = target_out + 'index.html'
|
|
12
|
+
# 解析文档
|
|
13
|
+
parser = PPZ::FileDocParser.new TARGET_IN
|
|
14
|
+
# 拼接上 css 文件链接
|
|
15
|
+
output_html = '<link rel="stylesheet" href="./index.css"/>' + parser.get_model.to_html
|
|
16
|
+
# 输出
|
|
17
|
+
PPZ::Func::write_to_file output_html_path.to_s, output_html
|
data/bin/folder.rb
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
require_relative '../lib/parser/folder/index'
|
|
2
|
+
|
|
3
|
+
puts '输入文件夹: ' + TARGET_IN
|
|
4
|
+
puts '输出文件夹: ' + TARGET_OUT
|
|
5
|
+
puts
|
|
6
|
+
|
|
7
|
+
FileUtils.cp PPZMain::CSS_FILE_PATH, ((Pathname TARGET_OUT) + 'style.css').to_s
|
|
8
|
+
|
|
9
|
+
model = PPZ::Folder::FolderModel.new TARGET_IN, 0
|
|
10
|
+
model.compile TARGET_OUT
|
data/bin/ppz
CHANGED
|
@@ -5,14 +5,10 @@ require_relative './common'
|
|
|
5
5
|
require 'fileutils'
|
|
6
6
|
require 'pathname'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
TARGET_IN, TARGET_OUT, IS_FOLDER = PPZMain::Util.get_in_and_out
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
model = parser.get_model
|
|
16
|
-
output_html = '<link rel="stylesheet" href="./index.css"/>' + model.to_html
|
|
17
|
-
PPZ::Func::write_to_file output_html_path.to_s, output_html
|
|
18
|
-
FileUtils.cp PPZMain::CSS_FILE_PATH, output_css_path
|
|
10
|
+
if IS_FOLDER
|
|
11
|
+
require_relative './folder.rb'
|
|
12
|
+
else
|
|
13
|
+
require_relative './doc.rb'
|
|
14
|
+
end
|
data/lib/func/util.rb
CHANGED
|
@@ -4,7 +4,7 @@ class PPZ::Func
|
|
|
4
4
|
if File.exist? filepath
|
|
5
5
|
throw '文件已存在'
|
|
6
6
|
end
|
|
7
|
-
file = File.new filepath, 'w'
|
|
7
|
+
file = File.new filepath, mode: 'w:UTF-8'
|
|
8
8
|
file.print data
|
|
9
9
|
file.close
|
|
10
10
|
end
|
|
@@ -17,5 +17,13 @@ class PPZ::Func
|
|
|
17
17
|
def class_has_const? instance, const_name
|
|
18
18
|
has_const? instance.class, const_name
|
|
19
19
|
end
|
|
20
|
+
|
|
21
|
+
def format_path path
|
|
22
|
+
if ['/', '\\'].include? path[-1]
|
|
23
|
+
path[0...-1]
|
|
24
|
+
else
|
|
25
|
+
path
|
|
26
|
+
end
|
|
27
|
+
end
|
|
20
28
|
end
|
|
21
29
|
end
|
data/lib/parser/folder/index.rb
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
# 解析一个文件夹里的 .ppz 文件
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
module PPZ::Folder
|
|
4
|
+
class FolderParser
|
|
5
|
+
def initialize
|
|
6
|
+
@context = Context.new
|
|
7
|
+
end
|
|
6
8
|
end
|
|
7
|
-
|
|
9
|
+
|
|
10
|
+
require_relative './model/abstract'
|
|
11
|
+
require_relative './model/folder'
|
|
12
|
+
require_relative './model/file/abstract'
|
|
13
|
+
require_relative './model/file/other'
|
|
14
|
+
require_relative './model/file/ppz'
|
|
15
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module PPZ::Folder
|
|
2
|
+
class AbstractModel
|
|
3
|
+
attr_reader :index, :name
|
|
4
|
+
|
|
5
|
+
def initialize path, level
|
|
6
|
+
throw '文件(夹)的名字得是字符串啊' unless path.is_a? String
|
|
7
|
+
@path = path
|
|
8
|
+
@basename = File.basename path
|
|
9
|
+
@level = level
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.from_path path, level
|
|
13
|
+
level += 1
|
|
14
|
+
if Dir.exist? path
|
|
15
|
+
FolderModel.new path, level
|
|
16
|
+
elsif File.exist? path
|
|
17
|
+
AbstractFileModel.from_path path, level
|
|
18
|
+
else
|
|
19
|
+
throw path + '不存在?'
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def get_css_path
|
|
24
|
+
('../' * @level) + 'style.css'
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module PPZ::Folder
|
|
2
|
+
class AbstractFileModel < AbstractModel
|
|
3
|
+
def self.from_path path, level
|
|
4
|
+
if (File.extname path) == '.ppz'
|
|
5
|
+
PPZFileModel.new path, level
|
|
6
|
+
else
|
|
7
|
+
OtherFileModel.new path, level
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
attr_reader :file_ext
|
|
12
|
+
|
|
13
|
+
def initialize path, level
|
|
14
|
+
super
|
|
15
|
+
unless /^((\d+)_)?([^\.]+)(\.[^\.]+)?$/.match @basename
|
|
16
|
+
throw '文件的命名方式不太理解哦:' + path
|
|
17
|
+
end
|
|
18
|
+
@index = $2?($2.to_i):(Float::INFINITY)
|
|
19
|
+
@name = $3
|
|
20
|
+
@file_ext = $4 || ''
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module PPZ::Folder
|
|
2
|
+
class PPZFileModel < AbstractFileModel
|
|
3
|
+
def _compile dir_out
|
|
4
|
+
parser = PPZ::FileDocParser.new @path
|
|
5
|
+
html_str = "<link rel=\"stylesheet\" href=\"#{get_css_path}\"/>" +
|
|
6
|
+
parser.get_model.to_html
|
|
7
|
+
PPZ::Func::write_to_file (dir_out + '/' + @name + '.html'), html_str
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module PPZ::Folder
|
|
2
|
+
class FolderModel < AbstractModel
|
|
3
|
+
def initialize path, level
|
|
4
|
+
super
|
|
5
|
+
/^((\d+)_)?(.+)/.match @basename
|
|
6
|
+
@index = $2?($2.to_i):(Float::INFINITY)
|
|
7
|
+
@name = $3
|
|
8
|
+
|
|
9
|
+
@children = []
|
|
10
|
+
(Dir.children path).each do |child_name|
|
|
11
|
+
@children.push AbstractModel.from_path (path + '/' + child_name), level
|
|
12
|
+
end
|
|
13
|
+
@children.sort! do |a, b|
|
|
14
|
+
a.index <=> b.index
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def _compile out_dir # compile 是 _compile 的安全版本
|
|
19
|
+
PPZ::Func.write_to_file (out_dir + '/' + @name + '.html'),
|
|
20
|
+
"<link rel=\"stylesheet\" href=\"#{get_css_path}\"/><ul>#{
|
|
21
|
+
@children
|
|
22
|
+
.map do |child|
|
|
23
|
+
if child.file_ext == '.ppz'
|
|
24
|
+
"<li><a href=\"./#{@name}/#{child.name}.html\">#{child.name}</a></li>"
|
|
25
|
+
else
|
|
26
|
+
''
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
.join
|
|
30
|
+
}</ul>"
|
|
31
|
+
|
|
32
|
+
children_dir = out_dir + '/' + @name
|
|
33
|
+
Dir.mkdir children_dir
|
|
34
|
+
@children.each { |child| child._compile children_dir }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def compile out_dir
|
|
38
|
+
unless out_dir.is_a? String
|
|
39
|
+
throw 'out_dir 只能是字符串'
|
|
40
|
+
end
|
|
41
|
+
unless Dir.exist? out_dir
|
|
42
|
+
throw "out_dir #{out_dir} 不存在"
|
|
43
|
+
end
|
|
44
|
+
if ['/', '\\'].include? out_dir[-1]
|
|
45
|
+
_compile out_dir[0...-1]
|
|
46
|
+
else
|
|
47
|
+
_compile out_dir
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
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.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- wuse
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2021-02-
|
|
11
|
+
date: 2021-02-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description:
|
|
14
14
|
email: 372301467@qq.com
|
|
@@ -20,6 +20,8 @@ files:
|
|
|
20
20
|
- asset/style/ppz.css
|
|
21
21
|
- asset/style/ppz.styl
|
|
22
22
|
- bin/common.rb
|
|
23
|
+
- bin/doc.rb
|
|
24
|
+
- bin/folder.rb
|
|
23
25
|
- bin/ppz
|
|
24
26
|
- lib/func/util.rb
|
|
25
27
|
- lib/model/abstract/model.rb
|
|
@@ -44,6 +46,11 @@ files:
|
|
|
44
46
|
- lib/parser/doc/file.rb
|
|
45
47
|
- lib/parser/doc/string.rb
|
|
46
48
|
- lib/parser/folder/index.rb
|
|
49
|
+
- lib/parser/folder/model/abstract.rb
|
|
50
|
+
- lib/parser/folder/model/file/abstract.rb
|
|
51
|
+
- lib/parser/folder/model/file/other.rb
|
|
52
|
+
- lib/parser/folder/model/file/ppz.rb
|
|
53
|
+
- lib/parser/folder/model/folder.rb
|
|
47
54
|
- lib/ppz.rb
|
|
48
55
|
homepage: https://github.com/daGaiGuanYu/ppz
|
|
49
56
|
licenses:
|