social_snippet 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.travis.yml +1 -2
- data/Rakefile +12 -0
- data/lib/social_snippet/api.rb +4 -4
- data/lib/social_snippet/api/completion_api.rb +1 -1
- data/lib/social_snippet/api/config_api.rb +3 -3
- data/lib/social_snippet/api/insert_snippet_api.rb +1 -1
- data/lib/social_snippet/api/install_repository_api.rb +5 -5
- data/lib/social_snippet/api/manifest_api.rb +5 -5
- data/lib/social_snippet/api/registry_api.rb +1 -1
- data/lib/social_snippet/api/search_api.rb +2 -2
- data/lib/social_snippet/api/show_api.rb +1 -1
- data/lib/social_snippet/api/update_repository_api.rb +9 -9
- data/lib/social_snippet/command_line/command.rb +2 -2
- data/lib/social_snippet/command_line/ssnip/main_command.rb +1 -1
- data/lib/social_snippet/command_line/sspm/sub_commands/complete_command.rb +1 -1
- data/lib/social_snippet/command_line/sspm/sub_commands/config_command.rb +3 -3
- data/lib/social_snippet/command_line/sspm/sub_commands/info_command.rb +1 -1
- data/lib/social_snippet/command_line/sspm/sub_commands/init_command.rb +1 -1
- data/lib/social_snippet/command_line/sspm/sub_commands/install_command.rb +4 -4
- data/lib/social_snippet/command_line/sspm/sub_commands/publish_command.rb +2 -2
- data/lib/social_snippet/command_line/sspm/sub_commands/search_command.rb +1 -1
- data/lib/social_snippet/command_line/sspm/sub_commands/update_command.rb +2 -2
- data/lib/social_snippet/config.rb +3 -3
- data/lib/social_snippet/context.rb +32 -11
- data/lib/social_snippet/registry/registry_client.rb +4 -4
- data/lib/social_snippet/registry/registry_resources/base.rb +13 -13
- data/lib/social_snippet/repository/repository_installer.rb +6 -6
- data/lib/social_snippet/repository/repository_manager.rb +11 -12
- data/lib/social_snippet/resolvers/base_resolver.rb +25 -11
- data/lib/social_snippet/resolvers/dep_resolver.rb +4 -4
- data/lib/social_snippet/resolvers/insert_resolver.rb +14 -13
- data/lib/social_snippet/snippet.rb +76 -55
- data/lib/social_snippet/tag.rb +28 -7
- data/lib/social_snippet/tag_parser.rb +47 -38
- data/lib/social_snippet/version.rb +1 -1
- data/spec/lib/api_spec.rb +4 -4
- data/spec/lib/command_line/sspm_config_spec.rb +3 -3
- data/spec/lib/command_line/sspm_init_spec.rb +1 -1
- data/spec/lib/command_line/sspm_install_spec.rb +5 -5
- data/spec/lib/command_line/sspm_search_spec.rb +1 -1
- data/spec/lib/context_spec.rb +29 -22
- data/spec/lib/core_spec.rb +12 -12
- data/spec/lib/insert_resolver_spec.rb +7 -7
- data/spec/lib/repository/repository_manager_spec.rb +1 -0
- data/spec/spec_helper.rb +15 -15
- data/test/core_test.rb +1062 -428
- metadata +2 -2
@@ -1,7 +1,10 @@
|
|
1
1
|
class SocialSnippet::Context
|
2
2
|
|
3
|
+
require "pathname"
|
4
|
+
|
3
5
|
attr_reader :flag_absolute
|
4
6
|
attr_reader :path
|
7
|
+
attr_reader :pathname
|
5
8
|
attr_reader :repo
|
6
9
|
attr_reader :ref
|
7
10
|
|
@@ -9,12 +12,18 @@ class SocialSnippet::Context
|
|
9
12
|
#
|
10
13
|
# @param new_path [String] The path of context
|
11
14
|
def initialize(new_path, new_repo = nil, new_ref = nil)
|
12
|
-
|
13
|
-
@path = new_path
|
15
|
+
set_path new_path
|
14
16
|
@repo = new_repo
|
15
17
|
@ref = new_ref
|
16
18
|
end
|
17
19
|
|
20
|
+
def set_path(new_path)
|
21
|
+
return if new_path.nil?
|
22
|
+
@path = new_path
|
23
|
+
@pathname = ::Pathname.new(path)
|
24
|
+
@flag_absolute = is_absolute_path(path)
|
25
|
+
end
|
26
|
+
|
18
27
|
# Check context in repo
|
19
28
|
#
|
20
29
|
# @return [Boolean]
|
@@ -31,25 +40,36 @@ class SocialSnippet::Context
|
|
31
40
|
if new_repo.nil?
|
32
41
|
if is_absolute_path(new_path)
|
33
42
|
@flag_absolute = true
|
34
|
-
|
43
|
+
set_path new_path
|
35
44
|
else
|
36
|
-
|
45
|
+
set_path move_path(new_path)
|
37
46
|
end
|
38
47
|
else
|
39
48
|
@flag_absolute = false
|
40
|
-
|
49
|
+
set_path new_path
|
41
50
|
@repo = new_repo
|
42
51
|
@ref = new_ref
|
43
52
|
end
|
44
53
|
end
|
45
54
|
|
55
|
+
def basename
|
56
|
+
pathname.basename.to_s unless path.nil?
|
57
|
+
end
|
58
|
+
|
59
|
+
def dirname
|
60
|
+
pathname.dirname.to_s unless path.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def root_text?
|
64
|
+
path.nil?
|
65
|
+
end
|
66
|
+
|
46
67
|
private
|
47
68
|
|
48
|
-
def
|
49
|
-
source =
|
50
|
-
source_file = source.pop
|
69
|
+
def move_path(new_path)
|
70
|
+
source = dirname.split("/")
|
51
71
|
dest = new_path.split("/")
|
52
|
-
|
72
|
+
destname = dest.pop
|
53
73
|
|
54
74
|
if is_absolute_path(path)
|
55
75
|
source.shift
|
@@ -64,13 +84,14 @@ class SocialSnippet::Context
|
|
64
84
|
end
|
65
85
|
|
66
86
|
if flag_absolute
|
67
|
-
"/" + source.join("/") + "/" +
|
87
|
+
"/" + source.join("/") + "/" + destname
|
68
88
|
else
|
69
|
-
source.join("/") + "/" +
|
89
|
+
source.join("/") + "/" + destname
|
70
90
|
end
|
71
91
|
end
|
72
92
|
|
73
93
|
private
|
94
|
+
|
74
95
|
# Check given text is absolute path
|
75
96
|
def is_absolute_path(s)
|
76
97
|
s[0] === "/"
|
@@ -2,12 +2,12 @@ module SocialSnippet::Registry
|
|
2
2
|
|
3
3
|
class RegistryClient
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :core
|
6
6
|
attr_reader :repositories
|
7
7
|
|
8
|
-
def initialize(
|
9
|
-
@
|
10
|
-
@repositories = RegistryResources::Repositories.new(
|
8
|
+
def initialize(new_core)
|
9
|
+
@core = new_core
|
10
|
+
@repositories = RegistryResources::Repositories.new(core)
|
11
11
|
end
|
12
12
|
|
13
13
|
end
|
@@ -5,27 +5,27 @@ module SocialSnippet::Registry::RegistryResources
|
|
5
5
|
|
6
6
|
class Base
|
7
7
|
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :core
|
9
9
|
attr_reader :rest_client
|
10
10
|
attr_reader :end_point
|
11
11
|
attr_reader :cookies
|
12
12
|
attr_reader :default_headers
|
13
13
|
|
14
|
-
def initialize(
|
15
|
-
@
|
16
|
-
@end_point =
|
14
|
+
def initialize(new_core)
|
15
|
+
@core = new_core
|
16
|
+
@end_point = core.config.sspm_url
|
17
17
|
@rest_client = ::RestClient::Resource.new(end_point)
|
18
18
|
@cookies = {}
|
19
19
|
@default_headers = {
|
20
20
|
:accept => :json,
|
21
21
|
}
|
22
22
|
|
23
|
-
|
23
|
+
core.logger.debug "registry: end-point = #{end_point}"
|
24
24
|
end
|
25
25
|
|
26
26
|
def post(req_path, params, headers = {})
|
27
|
-
|
28
|
-
|
27
|
+
core.logger.debug "registry: post: #{req_path}"
|
28
|
+
core.logger.debug params
|
29
29
|
csrf_token = fetch_csrf_token
|
30
30
|
|
31
31
|
# set headers
|
@@ -34,18 +34,18 @@ module SocialSnippet::Registry::RegistryResources
|
|
34
34
|
headers["X-CSRF-Token"] = csrf_token
|
35
35
|
|
36
36
|
# debug output
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
core.logger.debug "registry: post: csrf_token = #{csrf_token}"
|
38
|
+
core.logger.debug "registry: post: headers:"
|
39
|
+
core.logger.debug headers
|
40
40
|
|
41
41
|
parse_response rest_client[req_path].post(params.to_json, headers)
|
42
42
|
end
|
43
43
|
|
44
44
|
def get(req_path, headers = {})
|
45
|
-
|
45
|
+
core.logger.debug "registry: get #{req_path}"
|
46
46
|
headers.merge! default_headers
|
47
|
-
|
48
|
-
|
47
|
+
core.logger.debug "registry: headers:"
|
48
|
+
core.logger.debug headers
|
49
49
|
parse_response rest_client[req_path].get(headers)
|
50
50
|
end
|
51
51
|
|
@@ -4,20 +4,20 @@ module SocialSnippet::Repository
|
|
4
4
|
|
5
5
|
class RepositoryInstaller
|
6
6
|
|
7
|
-
attr_reader :
|
7
|
+
attr_reader :core
|
8
8
|
attr_reader :data
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@
|
10
|
+
def initialize(new_core)
|
11
|
+
@core = new_core
|
12
12
|
init_data
|
13
13
|
end
|
14
14
|
|
15
15
|
def path
|
16
|
-
|
16
|
+
core.config.install_path
|
17
17
|
end
|
18
18
|
|
19
19
|
def data_file
|
20
|
-
|
20
|
+
core.config.installed_repos_file
|
21
21
|
end
|
22
22
|
|
23
23
|
def init_data
|
@@ -61,7 +61,7 @@ module SocialSnippet::Repository
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def copy_repository(repo, options = {})
|
64
|
-
|
64
|
+
core.logger.debug "repository_installer: repo.path = #{repo.path}"
|
65
65
|
::FileUtils.cp_r repo.path, repo_path(repo.name)
|
66
66
|
end
|
67
67
|
|
@@ -5,15 +5,15 @@ module SocialSnippet::Repository
|
|
5
5
|
attr_reader :installer
|
6
6
|
attr_reader :repo_paths
|
7
7
|
attr_reader :repo_cache_path
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :core
|
9
9
|
|
10
10
|
# Constructor
|
11
11
|
#
|
12
|
-
# @param
|
13
|
-
def initialize(
|
14
|
-
@
|
15
|
-
@installer = ::SocialSnippet::Repository::RepositoryInstaller.new(
|
16
|
-
@repo_cache_path =
|
12
|
+
# @param new_core [::SocialSnippet::Core]
|
13
|
+
def initialize(new_core)
|
14
|
+
@core = new_core
|
15
|
+
@installer = ::SocialSnippet::Repository::RepositoryInstaller.new(core)
|
16
|
+
@repo_cache_path = core.config.repository_cache_path
|
17
17
|
@repo_paths = []
|
18
18
|
|
19
19
|
init_repo_paths
|
@@ -47,19 +47,18 @@ module SocialSnippet::Repository
|
|
47
47
|
::SocialSnippet::Snippet.new(resolve_snippet_path(context, tag))
|
48
48
|
end
|
49
49
|
|
50
|
-
# Resolve snippet path
|
50
|
+
# Resolve snippet path by context and tag
|
51
51
|
#
|
52
52
|
# @param context [::SocialSnippet::Context] The context of snippet
|
53
53
|
# @param tag [::SocialSnippet::Tag] The tag of snippet
|
54
54
|
def resolve_snippet_path(context, tag)
|
55
55
|
if tag.has_repo?
|
56
56
|
repo = find_repository_by_tag(tag)
|
57
|
-
|
57
|
+
repo.real_path tag.path
|
58
|
+
else
|
59
|
+
new_context = context.clone
|
60
|
+
new_context.dirname + "/" + tag.filename
|
58
61
|
end
|
59
|
-
|
60
|
-
new_context = context.clone
|
61
|
-
new_context.move tag.path
|
62
|
-
return new_context.path
|
63
62
|
end
|
64
63
|
|
65
64
|
# Find repository by tag
|
@@ -2,14 +2,14 @@ module SocialSnippet
|
|
2
2
|
|
3
3
|
class Resolvers::BaseResolver
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :core
|
6
6
|
attr_reader :visited
|
7
7
|
|
8
8
|
# Constructor
|
9
9
|
#
|
10
|
-
# @param
|
11
|
-
def initialize(
|
12
|
-
@
|
10
|
+
# @param new_core [::SocialSnippet::Core]
|
11
|
+
def initialize(new_core)
|
12
|
+
@core = new_core
|
13
13
|
@visited = Set.new
|
14
14
|
end
|
15
15
|
|
@@ -25,21 +25,35 @@ module SocialSnippet
|
|
25
25
|
t = tag_info[:tag].set_by_tag(base_tag)
|
26
26
|
new_context = context.clone
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
if new_context.root_text?
|
29
|
+
new_context.set_path ""
|
30
|
+
move_context_by_tag! new_context, t
|
31
|
+
else
|
32
|
+
move_context_by_tag! new_context, t
|
33
|
+
overwrite_tag_in_same_repository! new_context, t
|
34
|
+
update_tag_path_by_context! new_context, t
|
35
|
+
resolve_tag_repo_ref! t
|
36
|
+
end
|
32
37
|
|
33
|
-
|
38
|
+
resolve_tag_repo_ref! t
|
39
|
+
child_snippet = core.repo_manager.get_snippet(new_context, t)
|
40
|
+
t.set_path new_context.path
|
34
41
|
|
35
42
|
if block_given?
|
36
|
-
yield
|
43
|
+
yield t, tag_info[:line_no], child_snippet, new_context
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
41
48
|
private
|
42
49
|
|
50
|
+
def resolve_tag_repo_ref!(t)
|
51
|
+
if t.has_repo?
|
52
|
+
repo = core.repo_manager.find_repository_by_tag(t)
|
53
|
+
t.set_ref repo.latest_version(t.ref)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
43
57
|
def move_context_by_tag!(context, tag)
|
44
58
|
if tag.has_repo?
|
45
59
|
if tag.has_ref?
|
@@ -69,7 +83,7 @@ module SocialSnippet
|
|
69
83
|
|
70
84
|
# Resolve tag's ref
|
71
85
|
def resolve_tag_repo_ref!(tag)
|
72
|
-
repo =
|
86
|
+
repo = core.repo_manager.find_repository_by_tag(tag)
|
73
87
|
|
74
88
|
# not found
|
75
89
|
return if repo.nil?
|
@@ -6,10 +6,10 @@ module SocialSnippet
|
|
6
6
|
|
7
7
|
# Constructor
|
8
8
|
#
|
9
|
-
# @param
|
10
|
-
def initialize(
|
9
|
+
# @param core [::SocialSnippet::Core]
|
10
|
+
def initialize(core)
|
11
11
|
@dep_to = {} # dep_to[tag_from] = tag_to
|
12
|
-
super(
|
12
|
+
super(core)
|
13
13
|
end
|
14
14
|
|
15
15
|
# Find all missing depended snippets
|
@@ -20,7 +20,7 @@ module SocialSnippet
|
|
20
20
|
def find(snippet, context_from, tag_from)
|
21
21
|
raise "must be passed snippet" unless snippet.is_a?(Snippet)
|
22
22
|
|
23
|
-
found_tags = find_func
|
23
|
+
found_tags = find_func(snippet, context_from, tag_from)
|
24
24
|
found_tags.each do |tag_info|
|
25
25
|
# remove self from deps graph
|
26
26
|
tag = tag_info[:tag]
|
@@ -7,11 +7,11 @@ module SocialSnippet
|
|
7
7
|
|
8
8
|
# Constructor
|
9
9
|
#
|
10
|
-
# @param
|
11
|
-
def initialize(
|
10
|
+
# @param core [::SocialSnippet::Core]
|
11
|
+
def initialize(core, new_options = {})
|
12
12
|
@options = new_options
|
13
|
-
@deps_resolver = Resolvers::DepResolver.new(
|
14
|
-
super(
|
13
|
+
@deps_resolver = Resolvers::DepResolver.new(core)
|
14
|
+
super(core)
|
15
15
|
init_options
|
16
16
|
end
|
17
17
|
|
@@ -26,15 +26,13 @@ module SocialSnippet
|
|
26
26
|
def insert(text)
|
27
27
|
raise "must be passed string" unless text.is_a?(String)
|
28
28
|
|
29
|
-
context = Context.new("")
|
30
29
|
snippet = Snippet.new_text(text)
|
31
|
-
|
32
30
|
snippet.snippet_tags.each do |tag_info|
|
33
31
|
visit tag_info[:tag]
|
34
32
|
end
|
35
33
|
|
36
|
-
|
37
|
-
|
34
|
+
context = Context.new(nil)
|
35
|
+
insert_func(snippet, context).join($/)
|
38
36
|
end
|
39
37
|
|
40
38
|
private
|
@@ -68,7 +66,9 @@ module SocialSnippet
|
|
68
66
|
src = insert_func(snippet, context, tag)
|
69
67
|
|
70
68
|
options[:margin_top].times { inserter.insert "" }
|
71
|
-
|
69
|
+
# @snip -> @snippet
|
70
|
+
inserter.insert tag.to_snippet_tag unless snippet.no_tag?
|
71
|
+
# insert snippet text
|
72
72
|
inserter.insert src
|
73
73
|
options[:margin_bottom].times { inserter.insert "" }
|
74
74
|
|
@@ -85,11 +85,12 @@ module SocialSnippet
|
|
85
85
|
dep_tags.each do |tag_info|
|
86
86
|
sub_t = tag_info[:tag]
|
87
87
|
sub_c = tag_info[:context]
|
88
|
+
resolve_tag_repo_ref! sub_t
|
88
89
|
|
89
|
-
visit(tag) if is_self(
|
90
|
+
visit(tag) if is_self(sub_t, sub_c)
|
90
91
|
next if is_visited(sub_t)
|
91
92
|
|
92
|
-
next_snippet =
|
93
|
+
next_snippet = core.repo_manager.get_snippet(sub_c, sub_t)
|
93
94
|
insert_by_tag_and_context! inserter, next_snippet, sub_c, sub_t
|
94
95
|
end
|
95
96
|
end
|
@@ -109,10 +110,10 @@ module SocialSnippet
|
|
109
110
|
dep_tags.each do |tag_info|
|
110
111
|
tag = tag_info[:tag].to_path
|
111
112
|
dep_ind = dep_tags_index[tag]
|
112
|
-
dep_tags_hash[dep_ind] = deps_resolver.dep_to[tag].to_a.map {|tag| dep_tags_index[tag] }
|
113
|
+
dep_tags_hash[dep_ind] = deps_resolver.dep_to[tag].to_a.map {|tag| dep_tags_index[tag] }.reject(&:nil?)
|
113
114
|
end
|
114
115
|
|
115
|
-
dep_tags_hash.tsort.map {|k| dep_tags[k]}
|
116
|
+
dep_tags_hash.tsort.map {|k| dep_tags[k] }
|
116
117
|
end
|
117
118
|
|
118
119
|
end # BaseResolver
|
@@ -1,75 +1,96 @@
|
|
1
|
-
|
1
|
+
module SocialSnippet
|
2
2
|
|
3
|
-
|
4
|
-
attr_reader :code
|
3
|
+
class Snippet
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
read_file unless filepath.nil?
|
10
|
-
end
|
5
|
+
attr_reader :filepath
|
6
|
+
attr_reader :code
|
7
|
+
attr_reader :flag_no_tag
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
# Constructor
|
10
|
+
def initialize(snippet_path)
|
11
|
+
@filepath = snippet_path
|
12
|
+
read_file unless filepath.nil?
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
15
|
+
def read_file
|
16
|
+
@code = ::File.read(filepath).split($/)
|
17
|
+
end
|
20
18
|
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
def read_text(s)
|
20
|
+
raise "must be passed string" unless s.is_a?(String)
|
21
|
+
@code = s.split($/)
|
22
|
+
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def lines
|
25
|
+
@lines ||= new_lines
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
def snippet_tags
|
29
|
+
TagParser.find_snippet_tags lines
|
30
|
+
end
|
32
31
|
|
33
|
-
|
32
|
+
def snip_tags
|
33
|
+
TagParser.find_snip_tags lines
|
34
|
+
end
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
raise "must be passed string" unless s.is_a?(String)
|
38
|
-
snippet = self.new(nil)
|
39
|
-
snippet.read_text s
|
40
|
-
snippet
|
36
|
+
def no_tag?
|
37
|
+
flag_no_tag
|
41
38
|
end
|
42
39
|
|
43
|
-
|
40
|
+
class << self
|
44
41
|
|
45
|
-
|
42
|
+
# Create instance by text
|
43
|
+
def new_text(s)
|
44
|
+
raise "must be passed string" unless s.is_a?(String)
|
45
|
+
snippet = self.new(nil)
|
46
|
+
snippet.read_text s
|
47
|
+
snippet
|
48
|
+
end
|
46
49
|
|
47
|
-
|
48
|
-
def new_lines
|
49
|
-
tmp = code.clone
|
50
|
-
tmp = filter(tmp)
|
51
|
-
tmp
|
52
|
-
end
|
50
|
+
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
52
|
+
private
|
53
|
+
|
54
|
+
# Return filtered and styled lines
|
55
|
+
def new_lines
|
56
|
+
tmp = code.clone
|
57
|
+
tmp = filter(tmp)
|
58
|
+
tmp
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param lines [Array<String>]
|
62
|
+
def filter(lines)
|
63
|
+
lines = filter_range_cut(lines)
|
64
|
+
lines = filter_line_cut(lines)
|
65
|
+
lines = resolve_control_tags(lines)
|
66
|
+
lines
|
67
|
+
end
|
68
|
+
|
69
|
+
def resolve_control_tags(lines)
|
70
|
+
@flag_no_tag = (false === TagParser.find_no_tags(lines).empty?)
|
71
|
+
lines.reject {|s| Tag.is_control_tag? s }
|
72
|
+
end
|
59
73
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
74
|
+
def filter_line_cut(lines)
|
75
|
+
lines.select {|s| not Tag.is_cut? s }
|
76
|
+
end
|
77
|
+
|
78
|
+
def filter_range_cut(lines)
|
79
|
+
cut_level = 0
|
80
|
+
lines.select do |line|
|
81
|
+
if Tag.is_begin_cut?(line)
|
82
|
+
cut_level += 1
|
83
|
+
false
|
84
|
+
elsif Tag.is_end_cut?(line)
|
85
|
+
cut_level -= 1
|
86
|
+
false
|
87
|
+
else
|
88
|
+
cut_level === 0
|
89
|
+
end
|
71
90
|
end
|
72
91
|
end
|
92
|
+
|
73
93
|
end
|
74
94
|
|
75
95
|
end
|
96
|
+
|