srt_subtitle_validator 0.1.7 → 0.2.0
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/.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>
|