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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 381349e2fad6a19cbebb0256f972b89d987d362d3266ea06ba50bbdbac4e9798
4
- data.tar.gz: 7aadf7bdbbda2723092ba43459fdad1be56f18927416edb174859a6984645d67
3
+ metadata.gz: a6ecf116f7998efdb6f554563f6b5e9c447872cc3c8d4531fbdba899b986bfcf
4
+ data.tar.gz: 545155a99ebdca8a31cd3ec012c2e6a7971a379bd9b97eba7d867c755930a377
5
5
  SHA512:
6
- metadata.gz: 0a099ef949d0b07c73181271255466f13594b6e31da2cd68a11f2dc2ca172aea4ae46a9ffd05a6c40d2e8e1dd69b249ab48dd431464292e64cd293e2d32a2ce6
7
- data.tar.gz: 2d42597300a332d7cd902146b672ac170175fc3158e2b519dd03a394cc5fe18ed1283cbddcbe28b59714cb06e2f10506b559e5d526719b34731a8118c596d2de
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,12 @@
1
+ class Func
2
+ class << self
3
+ def write_to_file filepath, data
4
+ if File.exist? filepath
5
+ throw '文件已存在'
6
+ end
7
+ file = File.new filepath, 'w'
8
+ file.print data
9
+ file.close
10
+ end
11
+ end
12
+ end
@@ -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
+ ['&', '&amp;'],
24
+ ['<', '&lt;'],
25
+ ['>', '&gt;'],
26
+ [' ', '&nbsp;'],
27
+ ['"', '&quot;']
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,5 @@
1
+ require_relative './abstract'
2
+
3
+ class UnorderedListItemModel < AbstractListItemModel
4
+ REG_EXP = /^\++ /
5
+ end
@@ -0,0 +1,7 @@
1
+ require_relative '../../abstract/model.rb'
2
+
3
+ class AbstractListWrapperModel < AbstractWrapperModel
4
+ def to_html
5
+ "<#{self.class::TAG_NAME}>#{super}</#{self.class::TAG_NAME}>"
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ require_relative './abstract'
2
+
3
+ class UnorderedListWrapperModel < AbstractListWrapperModel
4
+ TAG_NAME = 'ul'
5
+ end
@@ -0,0 +1,15 @@
1
+ require_relative '../abstract/model'
2
+
3
+ class PModel < 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
+ "<p>#{@text}</p>"
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ require_relative '../abstract/wrapper-model'
2
+
3
+ class AbstractSectionModel < AbstractWrapperModel
4
+ def append section
5
+ if section.is_a? AbstractSectionModel
6
+ section.father = self
7
+ end
8
+ super
9
+ end
10
+ 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,7 @@
1
+ require_relative './abstract'
2
+
3
+ class RootSectionModel < AbstractSectionModel
4
+ def level
5
+ 0
6
+ end
7
+ 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,10 @@
1
+ require_relative '../abstract/model'
2
+
3
+ class SpecialItemModel < AbstractModel
4
+ def initialize line
5
+ @line = line
6
+ end
7
+ def to_html
8
+ "<div>#{@line}</div>"
9
+ end
10
+ 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
@@ -0,0 +1,6 @@
1
+ require_relative './file'
2
+
3
+ target = FileDocParser.new __FILE__
4
+
5
+ p target.readline;p target.readline;p target.readline;p target.readline;
6
+ p target.readline;p target.readline;p target.readline;p target.readline;
@@ -0,0 +1,12 @@
1
+ require_relative './abstract'
2
+
3
+ class StringDocParser < AbstractDocParser
4
+ def initialize str
5
+ super()
6
+ @lines = str.split /\n/
7
+ end
8
+
9
+ private def readline
10
+ @lines.shift
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ # 解析一个文件夹里的 .ppz 文件
2
+
3
+ class FolderParser
4
+ def initialize
5
+ @context = Context.new
6
+ end
7
+ 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.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: