srt_subtitle_validator 0.1.7 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/.rspec +1 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +49 -0
- data/lib/srt_subtitle_validator.rb +0 -19
- data/lib/srt_subtitle_validator/cli.rb +4 -5
- data/lib/srt_subtitle_validator/srt_block.rb +33 -0
- data/lib/srt_subtitle_validator/srt_file.rb +20 -27
- data/lib/srt_subtitle_validator/validator.rb +16 -17
- data/lib/srt_subtitle_validator/version.rb +1 -1
- data/pkg/Srt checker.workflow/Contents/Info.plist +31 -0
- data/pkg/Srt checker.workflow/Contents/QuickLook/Preview.png +0 -0
- data/pkg/Srt checker.workflow/Contents/QuickLook/Thumbnail.png +0 -0
- data/pkg/Srt checker.workflow/Contents/_CodeSignature/CodeDirectory +0 -0
- data/pkg/Srt checker.workflow/Contents/_CodeSignature/CodeRequirements +0 -0
- data/pkg/Srt checker.workflow/Contents/_CodeSignature/CodeRequirements-1 +0 -0
- data/pkg/Srt checker.workflow/Contents/_CodeSignature/CodeResources +126 -0
- data/pkg/Srt checker.workflow/Contents/_CodeSignature/CodeSignature +0 -0
- data/pkg/Srt checker.workflow/Contents/_CodeSignature/CodeTopDirectory +0 -0
- data/pkg/Srt checker.workflow/Contents/document.wflow +483 -0
- data/spec/fixtures/files/cp1250-crlf.srt +86 -0
- data/spec/fixtures/files/utf8-crlf.srt +86 -0
- data/spec/fixtures/files/utf8-invalid-blocks.srt +82 -0
- data/spec/spec_helper.rb +104 -0
- data/spec/srt_block_spec.rb +27 -0
- data/spec/srt_file_spec.rb +34 -0
- data/spec/srt_validator_spec.rb +31 -0
- data/srt_subtitle_validator.gemspec +8 -4
- metadata +58 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d2098fa1f10819731524d2da1e21eb37edb53da1e41846ba3c90c09fd42dd864
|
4
|
+
data.tar.gz: 5bfb2204e4372ef473a44760be35befbb0af5b6e685b9db4733b9c7b7871c128
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a6fc5241c8ba0a7f2284d6da86c46bdfc9b1477c680aa8f95b89804955e98626b55987f3144ef6d736822ddbeff9bf5296e7074f5e8b3d5f11b0a5ad60e4ec6
|
7
|
+
data.tar.gz: e48d42e0c29028f5f8db0478c45d2232dd33833b4086f45a9e02f5170515b6dc218a637c30f628f1538c4b62f706bdab61e0c171138c94336438fa963332491b
|
data/.gitignore
CHANGED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
srt_subtitle_validator (0.2.0)
|
5
|
+
thor (~> 1.0)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
coderay (1.1.3)
|
11
|
+
diff-lcs (1.4.4)
|
12
|
+
docile (1.3.2)
|
13
|
+
method_source (1.0.0)
|
14
|
+
pry (0.13.1)
|
15
|
+
coderay (~> 1.1)
|
16
|
+
method_source (~> 1.0)
|
17
|
+
rake (12.3.3)
|
18
|
+
rspec (3.9.0)
|
19
|
+
rspec-core (~> 3.9.0)
|
20
|
+
rspec-expectations (~> 3.9.0)
|
21
|
+
rspec-mocks (~> 3.9.0)
|
22
|
+
rspec-core (3.9.3)
|
23
|
+
rspec-support (~> 3.9.3)
|
24
|
+
rspec-expectations (3.9.2)
|
25
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
26
|
+
rspec-support (~> 3.9.0)
|
27
|
+
rspec-mocks (3.9.1)
|
28
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
+
rspec-support (~> 3.9.0)
|
30
|
+
rspec-support (3.9.3)
|
31
|
+
simplecov (0.19.0)
|
32
|
+
docile (~> 1.1)
|
33
|
+
simplecov-html (~> 0.11)
|
34
|
+
simplecov-html (0.12.3)
|
35
|
+
thor (1.0.1)
|
36
|
+
|
37
|
+
PLATFORMS
|
38
|
+
ruby
|
39
|
+
|
40
|
+
DEPENDENCIES
|
41
|
+
bundler (~> 2.0)
|
42
|
+
pry (~> 0.13)
|
43
|
+
rake (~> 12.3)
|
44
|
+
rspec (~> 3.9)
|
45
|
+
simplecov
|
46
|
+
srt_subtitle_validator!
|
47
|
+
|
48
|
+
BUNDLED WITH
|
49
|
+
2.1.4
|
@@ -1,26 +1,7 @@
|
|
1
1
|
require 'srt_subtitle_validator/version'
|
2
|
-
# require 'srt_subtitle_validator/srt_file'
|
3
2
|
require 'srt_subtitle_validator/validator'
|
4
3
|
|
5
4
|
module SrtSubtitleValidator
|
6
5
|
# Your code goes here...
|
7
6
|
|
8
7
|
end
|
9
|
-
|
10
|
-
class String
|
11
|
-
def blank?
|
12
|
-
to_s == ''
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
class NilClass
|
17
|
-
def blank?
|
18
|
-
true
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class Array
|
23
|
-
def blank?
|
24
|
-
empty?
|
25
|
-
end
|
26
|
-
end
|
@@ -13,14 +13,13 @@ module SrtSubtitleValidator
|
|
13
13
|
desc: 'Show version number and quit'
|
14
14
|
|
15
15
|
def self.srt_default_options
|
16
|
-
method_option :without_backup, :
|
17
|
-
method_option :output, :
|
18
|
-
method_option :encoding, :
|
16
|
+
method_option :without_backup, default: false, type: :boolean, desc: 'Skip backuping original SRT file'
|
17
|
+
method_option :output, aliases: '-o', default: nil, type: :string, desc: 'Output directory (file)'
|
18
|
+
method_option :encoding, aliases: '-e', default: "cp1250", type: :string, desc: 'Output directory (file)'
|
19
19
|
end
|
20
20
|
|
21
21
|
srt_default_options
|
22
22
|
desc 'check', 'Check SRT file. '
|
23
|
-
|
24
23
|
def check(*files)
|
25
24
|
files_to_convert = Array.new
|
26
25
|
Array(files).each do |file|
|
@@ -35,7 +34,7 @@ module SrtSubtitleValidator
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
if files_to_convert.any? && yes?("Try to convert #{files_to_convert.length} files ?")
|
38
|
-
files_to_convert.each{|f| f.convert_srt(options[:output], options[:without_backup])}
|
37
|
+
files_to_convert.each { |f| f.convert_srt(options[:output], options[:without_backup]) }
|
39
38
|
end
|
40
39
|
|
41
40
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SrtSubtitleValidator
|
2
|
+
class SrtBlock
|
3
|
+
attr_accessor :dialog_number, :dialog_time, :dialog_text
|
4
|
+
|
5
|
+
# @overload new(text)
|
6
|
+
# Block of subtitle content, it will be split automatically
|
7
|
+
# @param args [String] describe key param
|
8
|
+
# @overload new(text)
|
9
|
+
# @param dialog_number [String] number of sequence
|
10
|
+
# @param dialog_time [String] time of sequence
|
11
|
+
# @param dialog_text [String] subtitle text itself
|
12
|
+
def initialize(*args)
|
13
|
+
case args.count
|
14
|
+
when 1
|
15
|
+
blok = args[0].split("\n")
|
16
|
+
@dialog_number = blok.shift.to_i
|
17
|
+
@dialog_time = blok.shift
|
18
|
+
@dialog_text = blok.join("\n")
|
19
|
+
when 3
|
20
|
+
@dialog_number = args.shift.to_i
|
21
|
+
@dialog_time = args.shift
|
22
|
+
@dialog_text = args.shift.strip
|
23
|
+
else
|
24
|
+
raise ArgumentError
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @return [String] subtitle sequence block
|
29
|
+
def to_s
|
30
|
+
[@dialog_number, @dialog_time, @dialog_text].join("\n") + "\n\n"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,43 +1,36 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'srt_subtitle_validator/srt_block'
|
3
|
+
|
1
4
|
module SrtSubtitleValidator
|
2
5
|
class SrtFile
|
3
6
|
attr_reader :blocks, :length
|
4
7
|
attr_accessor :errors
|
8
|
+
|
9
|
+
# @param [String] source content of SRT file
|
10
|
+
# @param [Logger] logger object, optionally - by default log to STDOUT
|
5
11
|
def initialize(source, logger = nil)
|
6
12
|
@logger = logger || Logger.new(STDOUT)
|
7
|
-
@errors =
|
8
|
-
|
9
|
-
@
|
10
|
-
@blocks = x.split(/^\r?\n+/m).map { |n| i = SrtBlock.new(n); @srt_dialog_blocks[i.dialog_number] = i; i }
|
11
|
-
@length = !@blocks.empty? && @blocks.last.dialog_number || 0
|
12
|
-
@errors << 'File is zero size' if @length.zero?
|
13
|
+
@errors = []
|
14
|
+
@srt_dialog_blocks = {}
|
15
|
+
@source = source.dup.encode(Encoding::UTF_8).gsub(/\r/, '')
|
13
16
|
end
|
14
17
|
|
15
18
|
def valid?
|
16
|
-
|
17
|
-
|
19
|
+
@blocks = @source.split(/^\r?\n+/m).map do |n|
|
20
|
+
i = SrtBlock.new(n)
|
21
|
+
@srt_dialog_blocks[i.dialog_number] = i
|
22
|
+
i
|
18
23
|
end
|
24
|
+
@length = !@blocks.empty? && @blocks.last.dialog_number || 0
|
25
|
+
@errors << 'File is zero size' if @length.zero?
|
26
|
+
@errors << 'Numbers sequence is corrupted' unless @blocks.count == @length
|
19
27
|
@errors.empty?
|
20
28
|
end
|
21
29
|
|
22
|
-
|
23
|
-
|
24
|
-
def initialize(*args)
|
25
|
-
case args.count
|
26
|
-
when 1
|
27
|
-
blok = args[0].split("\n")
|
28
|
-
@dialog_number = blok.shift.to_i
|
29
|
-
@dialog_time = blok.shift
|
30
|
-
@dialog_text = blok.join("\n")
|
31
|
-
when 3
|
32
|
-
@dialog_number, @dialog_time, @dialog_text = args
|
33
|
-
else
|
34
|
-
raise ArgumentError
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def to_s
|
39
|
-
[@dialog_number, @dialog_time, @dialog_text].join("\n") + "\n\n"
|
40
|
-
end
|
30
|
+
def inspect
|
31
|
+
"<SrtSubtitleValidator::SrtFile ...>"
|
41
32
|
end
|
33
|
+
|
34
|
+
|
42
35
|
end
|
43
36
|
end
|
@@ -1,19 +1,23 @@
|
|
1
|
+
require 'srt_subtitle_validator/srt_block'
|
1
2
|
require 'srt_subtitle_validator/srt_file'
|
3
|
+
|
2
4
|
class InvalidFile < ArgumentError; end
|
5
|
+
|
3
6
|
module SrtSubtitleValidator
|
4
7
|
class Validator
|
5
8
|
|
6
9
|
require 'logger'
|
7
10
|
require 'tempfile'
|
8
|
-
|
11
|
+
|
9
12
|
attr_reader :srt, :path, :file_name
|
10
13
|
|
11
14
|
def initialize(file_path, encoding = nil, logger = nil)
|
12
15
|
@logger = logger || Logger.new(STDOUT)
|
13
16
|
@path = File.absolute_path(file_path).strip
|
14
17
|
raise InvalidFile unless File.extname(@path) == '.srt'
|
18
|
+
|
15
19
|
@file_name = File.basename(@path)
|
16
|
-
parse_srt(File.read(@path, :
|
20
|
+
parse_srt(File.read(@path, encoding: (encoding || Encoding::UTF_8)))
|
17
21
|
end
|
18
22
|
|
19
23
|
def valid?
|
@@ -43,7 +47,7 @@ module SrtSubtitleValidator
|
|
43
47
|
@logger.info ' > Create new number sequence...'
|
44
48
|
@srt.blocks.each_with_index do |block, index|
|
45
49
|
number = index + 1
|
46
|
-
n = SrtSubtitleValidator::
|
50
|
+
n = SrtSubtitleValidator::SrtBlock.new(number, block.dialog_time, block.dialog_text)
|
47
51
|
@new_srt.write(n.to_s)
|
48
52
|
end
|
49
53
|
end
|
@@ -51,16 +55,13 @@ module SrtSubtitleValidator
|
|
51
55
|
def output_file(output = nil)
|
52
56
|
if output.to_s.empty?
|
53
57
|
@path
|
58
|
+
elsif File.directory?(output)
|
59
|
+
File.join(output, @file_name)
|
54
60
|
else
|
55
|
-
|
56
|
-
File.join(output, @file_name)
|
57
|
-
else
|
58
|
-
output
|
59
|
-
end
|
61
|
+
output
|
60
62
|
end
|
61
63
|
end
|
62
64
|
|
63
|
-
|
64
65
|
def backup_original_file
|
65
66
|
@logger.info ' > Create backup...'
|
66
67
|
backup_suffix = 1
|
@@ -73,15 +74,13 @@ module SrtSubtitleValidator
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def parse_srt(raw, with_fallback = true)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
77
|
+
@srt = SrtSubtitleValidator::SrtFile.new(raw)
|
78
|
+
@srt.valid?
|
79
|
+
rescue ArgumentError => e
|
80
|
+
if e.to_s == 'invalid byte sequence in UTF-8' && with_fallback
|
81
|
+
parse_srt(raw.force_encoding(Encoding::CP1250), false)
|
82
|
+
@srt.errors << 'Invalid encoding'
|
83
83
|
end
|
84
|
-
|
85
84
|
end
|
86
85
|
|
87
86
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>NSServices</key>
|
6
|
+
<array>
|
7
|
+
<dict>
|
8
|
+
<key>NSBackgroundColorName</key>
|
9
|
+
<string>background</string>
|
10
|
+
<key>NSIconName</key>
|
11
|
+
<string>NSActionTemplate</string>
|
12
|
+
<key>NSMenuItem</key>
|
13
|
+
<dict>
|
14
|
+
<key>default</key>
|
15
|
+
<string>Srt checker</string>
|
16
|
+
</dict>
|
17
|
+
<key>NSMessage</key>
|
18
|
+
<string>runWorkflowAsService</string>
|
19
|
+
<key>NSRequiredContext</key>
|
20
|
+
<dict>
|
21
|
+
<key>NSApplicationIdentifier</key>
|
22
|
+
<string>com.apple.finder</string>
|
23
|
+
</dict>
|
24
|
+
<key>NSSendFileTypes</key>
|
25
|
+
<array>
|
26
|
+
<string>public.item</string>
|
27
|
+
</array>
|
28
|
+
</dict>
|
29
|
+
</array>
|
30
|
+
</dict>
|
31
|
+
</plist>
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,126 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>files</key>
|
6
|
+
<dict/>
|
7
|
+
<key>files2</key>
|
8
|
+
<dict>
|
9
|
+
<key>QuickLook/Preview.png</key>
|
10
|
+
<dict>
|
11
|
+
<key>hash</key>
|
12
|
+
<data>
|
13
|
+
QvSQtn0emI9aFt4vHBUmb79bkYw=
|
14
|
+
</data>
|
15
|
+
<key>hash2</key>
|
16
|
+
<data>
|
17
|
+
NVQadZbSXOKqXHauLdgbzLrB7FU9scqDiByE5rGAX6o=
|
18
|
+
</data>
|
19
|
+
</dict>
|
20
|
+
<key>document.wflow</key>
|
21
|
+
<dict>
|
22
|
+
<key>cdhash</key>
|
23
|
+
<data>
|
24
|
+
LMMprsQPeyqSbXqO7e2go4nfRHE=
|
25
|
+
</data>
|
26
|
+
<key>requirement</key>
|
27
|
+
<string>identifier document and anchor apple generic and certificate leaf[subject.CN] = 0x4d616320446576656c6f7065723a204c756bc3a1c5a120506f6b6f726e792028345941444338534e353629 and certificate 1[field.1.2.840.113635.100.6.2.1] /* exists */</string>
|
28
|
+
</dict>
|
29
|
+
</dict>
|
30
|
+
<key>rules</key>
|
31
|
+
<dict>
|
32
|
+
<key>^Resources/</key>
|
33
|
+
<true/>
|
34
|
+
<key>^Resources/.*\.lproj/</key>
|
35
|
+
<dict>
|
36
|
+
<key>optional</key>
|
37
|
+
<true/>
|
38
|
+
<key>weight</key>
|
39
|
+
<real>1000</real>
|
40
|
+
</dict>
|
41
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
42
|
+
<dict>
|
43
|
+
<key>omit</key>
|
44
|
+
<true/>
|
45
|
+
<key>weight</key>
|
46
|
+
<real>1100</real>
|
47
|
+
</dict>
|
48
|
+
<key>^version.plist$</key>
|
49
|
+
<true/>
|
50
|
+
</dict>
|
51
|
+
<key>rules2</key>
|
52
|
+
<dict>
|
53
|
+
<key>.*\.dSYM($|/)</key>
|
54
|
+
<dict>
|
55
|
+
<key>weight</key>
|
56
|
+
<real>11</real>
|
57
|
+
</dict>
|
58
|
+
<key>^(.*/)?\.DS_Store$</key>
|
59
|
+
<dict>
|
60
|
+
<key>omit</key>
|
61
|
+
<true/>
|
62
|
+
<key>weight</key>
|
63
|
+
<real>2000</real>
|
64
|
+
</dict>
|
65
|
+
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
66
|
+
<dict>
|
67
|
+
<key>nested</key>
|
68
|
+
<true/>
|
69
|
+
<key>weight</key>
|
70
|
+
<real>10</real>
|
71
|
+
</dict>
|
72
|
+
<key>^.*</key>
|
73
|
+
<true/>
|
74
|
+
<key>^Info\.plist$</key>
|
75
|
+
<dict>
|
76
|
+
<key>omit</key>
|
77
|
+
<true/>
|
78
|
+
<key>weight</key>
|
79
|
+
<real>20</real>
|
80
|
+
</dict>
|
81
|
+
<key>^PkgInfo$</key>
|
82
|
+
<dict>
|
83
|
+
<key>omit</key>
|
84
|
+
<true/>
|
85
|
+
<key>weight</key>
|
86
|
+
<real>20</real>
|
87
|
+
</dict>
|
88
|
+
<key>^Resources/</key>
|
89
|
+
<dict>
|
90
|
+
<key>weight</key>
|
91
|
+
<real>20</real>
|
92
|
+
</dict>
|
93
|
+
<key>^Resources/.*\.lproj/</key>
|
94
|
+
<dict>
|
95
|
+
<key>optional</key>
|
96
|
+
<true/>
|
97
|
+
<key>weight</key>
|
98
|
+
<real>1000</real>
|
99
|
+
</dict>
|
100
|
+
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
101
|
+
<dict>
|
102
|
+
<key>omit</key>
|
103
|
+
<true/>
|
104
|
+
<key>weight</key>
|
105
|
+
<real>1100</real>
|
106
|
+
</dict>
|
107
|
+
<key>^[^/]+$</key>
|
108
|
+
<dict>
|
109
|
+
<key>nested</key>
|
110
|
+
<true/>
|
111
|
+
<key>weight</key>
|
112
|
+
<real>10</real>
|
113
|
+
</dict>
|
114
|
+
<key>^embedded\.provisionprofile$</key>
|
115
|
+
<dict>
|
116
|
+
<key>weight</key>
|
117
|
+
<real>20</real>
|
118
|
+
</dict>
|
119
|
+
<key>^version\.plist$</key>
|
120
|
+
<dict>
|
121
|
+
<key>weight</key>
|
122
|
+
<real>20</real>
|
123
|
+
</dict>
|
124
|
+
</dict>
|
125
|
+
</dict>
|
126
|
+
</plist>
|