titlekit 1.0.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.
Files changed (119) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.travis.yml +3 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +22 -0
  6. data/README.md +335 -0
  7. data/Rakefile +8 -0
  8. data/lib/titlekit/have.rb +90 -0
  9. data/lib/titlekit/job.rb +446 -0
  10. data/lib/titlekit/parsers/ass.rb +175 -0
  11. data/lib/titlekit/parsers/ass.treetop +72 -0
  12. data/lib/titlekit/parsers/srt.rb +139 -0
  13. data/lib/titlekit/parsers/srt.treetop +73 -0
  14. data/lib/titlekit/parsers/ssa.rb +201 -0
  15. data/lib/titlekit/parsers/ssa.treetop +72 -0
  16. data/lib/titlekit/specification.rb +131 -0
  17. data/lib/titlekit/utilities.rb +3 -0
  18. data/lib/titlekit/version.rb +3 -0
  19. data/lib/titlekit/want.rb +24 -0
  20. data/lib/titlekit.rb +9 -0
  21. data/spec/ass_spec.rb +113 -0
  22. data/spec/automatic_grouping/automatic_grouping_spec.rb +55 -0
  23. data/spec/automatic_grouping/dual_tracks/expected.srt +15 -0
  24. data/spec/automatic_grouping/dual_tracks/one.srt +11 -0
  25. data/spec/automatic_grouping/dual_tracks/out.srt +15 -0
  26. data/spec/automatic_grouping/dual_tracks/two.srt +11 -0
  27. data/spec/automatic_grouping/single_track/expected.srt +24 -0
  28. data/spec/automatic_grouping/single_track/one.srt +11 -0
  29. data/spec/automatic_grouping/single_track/out.srt +24 -0
  30. data/spec/automatic_grouping/single_track/two.srt +11 -0
  31. data/spec/encoding_detection/a/in.ass +0 -0
  32. data/spec/encoding_detection/b/in.srt +2389 -0
  33. data/spec/encoding_detection/b/out.srt +2389 -0
  34. data/spec/encoding_detection/c/in.srt +5320 -0
  35. data/spec/encoding_detection/c/out.srt +5320 -0
  36. data/spec/encoding_detection/encoding_detection_spec.rb +81 -0
  37. data/spec/files/ass/authentic.ass +0 -0
  38. data/spec/files/ass/hard.ass +37 -0
  39. data/spec/files/ass/simple.ass +28 -0
  40. data/spec/files/srt/authentic.srt +2708 -0
  41. data/spec/files/srt/coordinates.srt +13 -0
  42. data/spec/files/srt/simple.srt +12 -0
  43. data/spec/files/ssa/simple.ssa +26 -0
  44. data/spec/files/try/unsupported-output.try +0 -0
  45. data/spec/files/try/unsupported.try +7 -0
  46. data/spec/format_conversion/ass_srt/expected.srt +2327 -0
  47. data/spec/format_conversion/ass_srt/in.ass +485 -0
  48. data/spec/format_conversion/ass_srt/out.srt +2327 -0
  49. data/spec/format_conversion/format_conversion_spec.rb +112 -0
  50. data/spec/format_conversion/srt_ass/expected.ass +19 -0
  51. data/spec/format_conversion/srt_ass/in.srt +12 -0
  52. data/spec/format_conversion/srt_ass/out.ass +19 -0
  53. data/spec/format_conversion/srt_ssa/expected.ssa +19 -0
  54. data/spec/format_conversion/srt_ssa/in.srt +12 -0
  55. data/spec/format_conversion/srt_ssa/out.ssa +19 -0
  56. data/spec/format_conversion/ssa_srt/expected.srt +9 -0
  57. data/spec/format_conversion/ssa_srt/in.ssa +26 -0
  58. data/spec/format_conversion/ssa_srt/out.srt +9 -0
  59. data/spec/job_spec.rb +162 -0
  60. data/spec/simultaneous_subtitles/dual/ass/expected.ass +22 -0
  61. data/spec/simultaneous_subtitles/dual/ass/out.ass +22 -0
  62. data/spec/simultaneous_subtitles/dual/one.srt +11 -0
  63. data/spec/simultaneous_subtitles/dual/srt/expected.srt +27 -0
  64. data/spec/simultaneous_subtitles/dual/srt/out.srt +27 -0
  65. data/spec/simultaneous_subtitles/dual/ssa/expected.ssa +22 -0
  66. data/spec/simultaneous_subtitles/dual/ssa/out.ssa +22 -0
  67. data/spec/simultaneous_subtitles/dual/two.srt +11 -0
  68. data/spec/simultaneous_subtitles/simultaneous_subtitles_spec.rb +220 -0
  69. data/spec/simultaneous_subtitles/triple/ass/expected.ass +25 -0
  70. data/spec/simultaneous_subtitles/triple/ass/out.ass +25 -0
  71. data/spec/simultaneous_subtitles/triple/one.srt +11 -0
  72. data/spec/simultaneous_subtitles/triple/srt/expected.srt +55 -0
  73. data/spec/simultaneous_subtitles/triple/srt/out.srt +55 -0
  74. data/spec/simultaneous_subtitles/triple/ssa/expected.ssa +25 -0
  75. data/spec/simultaneous_subtitles/triple/ssa/out.ssa +25 -0
  76. data/spec/simultaneous_subtitles/triple/three.srt +11 -0
  77. data/spec/simultaneous_subtitles/triple/two.srt +11 -0
  78. data/spec/simultaneous_subtitles/triple_plus/ass/expected.ass +93 -0
  79. data/spec/simultaneous_subtitles/triple_plus/ass/out.ass +93 -0
  80. data/spec/simultaneous_subtitles/triple_plus/five.srt +11 -0
  81. data/spec/simultaneous_subtitles/triple_plus/four.srt +11 -0
  82. data/spec/simultaneous_subtitles/triple_plus/one.srt +11 -0
  83. data/spec/simultaneous_subtitles/triple_plus/six.srt +11 -0
  84. data/spec/simultaneous_subtitles/triple_plus/srt/expected.srt +149 -0
  85. data/spec/simultaneous_subtitles/triple_plus/srt/out.srt +149 -0
  86. data/spec/simultaneous_subtitles/triple_plus/ssa/expected.ssa +93 -0
  87. data/spec/simultaneous_subtitles/triple_plus/ssa/out.ssa +93 -0
  88. data/spec/simultaneous_subtitles/triple_plus/three.srt +11 -0
  89. data/spec/simultaneous_subtitles/triple_plus/two.srt +11 -0
  90. data/spec/spec_helper.rb +7 -0
  91. data/spec/specifications_spec.rb +138 -0
  92. data/spec/srt_spec.rb +134 -0
  93. data/spec/ssa_spec.rb +90 -0
  94. data/spec/timecode_correction/double_reference/expected.srt +13 -0
  95. data/spec/timecode_correction/double_reference/in.srt +12 -0
  96. data/spec/timecode_correction/double_reference/out.srt +13 -0
  97. data/spec/timecode_correction/framerate/expected.srt +5 -0
  98. data/spec/timecode_correction/framerate/in.srt +4 -0
  99. data/spec/timecode_correction/framerate/out.srt +5 -0
  100. data/spec/timecode_correction/framerate_plus_reference/expected.srt +13 -0
  101. data/spec/timecode_correction/framerate_plus_reference/in.srt +12 -0
  102. data/spec/timecode_correction/framerate_plus_reference/out.srt +13 -0
  103. data/spec/timecode_correction/single_reference/expected.srt +13 -0
  104. data/spec/timecode_correction/single_reference/in.srt +12 -0
  105. data/spec/timecode_correction/single_reference/out.srt +13 -0
  106. data/spec/timecode_correction/timecode_correction_spec.rb +124 -0
  107. data/spec/transcoding/gb2312-ascii/in.srt +12 -0
  108. data/spec/transcoding/iso-8859-1_utf-8/expected.srt +12 -0
  109. data/spec/transcoding/iso-8859-1_utf-8/in.srt +11 -0
  110. data/spec/transcoding/iso-8859-1_utf-8/out.srt +12 -0
  111. data/spec/transcoding/transcoding_spec.rb +116 -0
  112. data/spec/transcoding/utf-8_gbk/expected.srt +12 -0
  113. data/spec/transcoding/utf-8_gbk/in.srt +11 -0
  114. data/spec/transcoding/utf-8_gbk/out.srt +12 -0
  115. data/spec/transcoding/windows-1252_utf-8/expected.srt +12 -0
  116. data/spec/transcoding/windows-1252_utf-8/in.srt +11 -0
  117. data/spec/transcoding/windows-1252_utf-8/out.srt +12 -0
  118. data/titlekit.gemspec +28 -0
  119. metadata +313 -0
data/spec/ass_spec.rb ADDED
@@ -0,0 +1,113 @@
1
+ require File.join(File.expand_path(__dir__), 'spec_helper')
2
+
3
+ describe Titlekit::ASS do
4
+
5
+ describe '.import' do
6
+
7
+ context 'with a simple file' do
8
+ let(:subtitles) do
9
+ Titlekit::ASS.import(File.read('spec/files/ass/simple.ass'))
10
+ end
11
+
12
+ it 'parses and builds 3 subtitles' do
13
+ expect(subtitles.length).to eq(2)
14
+ end
15
+
16
+ it 'parses and builds correct ids' do
17
+ expect(subtitles[0][:id]).to eq(1)
18
+ end
19
+
20
+ it 'parses and builds correct timecodes' do
21
+ expect(subtitles[1][:start]).to eq(120.99)
22
+ expect(subtitles[1][:end]).to eq(122.87)
23
+ end
24
+
25
+ it 'parses and builds correct lines' do
26
+ expect(subtitles[1][:lines]).to eq("Est-ce vraiment Naruto ?")
27
+ end
28
+ end
29
+
30
+ context 'with a hard file' do
31
+ let(:subtitles) do
32
+ Titlekit::ASS.import(File.read('spec/files/ass/hard.ass'))
33
+ end
34
+
35
+ it 'parses and builds 3 subtitles' do
36
+ expect(subtitles.length).to eq(17)
37
+ end
38
+
39
+ it 'parses and builds correct ids' do
40
+ expect(subtitles[0][:id]).to eq(1)
41
+ end
42
+
43
+ it 'parses and builds correct timecodes' do
44
+ expect(subtitles[8][:start]).to eq(4)
45
+ expect(subtitles[8][:end]).to eq(6)
46
+ end
47
+
48
+ it 'parses and builds correct lines' do
49
+ expect(subtitles[1][:lines]).to eq("هل تعمل اللغة العربية؟\n")
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '.export' do
55
+ it 'should export valid ASS' do
56
+ subtitles = [
57
+ {
58
+ start: 1.5,
59
+ end: 3.7,
60
+ lines: 'Eine feine Testung haben sie da!'
61
+ },
62
+ {
63
+ id: 2,
64
+ start: 1.5,
65
+ end: 3.7,
66
+ lines: '¡Sí claro! Pero que lastima que no es 100% español ...'
67
+ },
68
+ {
69
+ id: 3,
70
+ start: 1.5,
71
+ end: 3.7,
72
+ lines: 'Oh yeah ... 寧為太平犬,不做亂世人'
73
+ }
74
+ ]
75
+
76
+ expected = <<-EXPECTED
77
+ [Script Info]
78
+ ScriptType: v4.00+
79
+
80
+ [V4+ Styles]
81
+ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
82
+ Style: Default,Arial,16,&H00FFFFFF,&H00FFFFFF,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,2,20,20,20,1
83
+ Style: Top,Arial,16,&H00FFFFFF,&H00FFFFFF,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,8,20,20,20,1
84
+ Style: Middle,Arial,16,&H00FFFFFF,&H00FFFFFF,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,5,20,20,20,1
85
+ Style: EDF393,Arial,16,&H0093F3ED,&H0093F3ED,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,2,20,20,20,1
86
+ Style: F5E665,Arial,16,&H0065E6F5,&H0065E6F5,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,2,20,20,20,1
87
+ Style: FFC472,Arial,16,&H0072C4FF,&H0072C4FF,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,2,20,20,20,1
88
+ Style: FFA891,Arial,16,&H0091A8FF,&H0091A8FF,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,2,20,20,20,1
89
+ Style: 89BABE,Arial,16,&H00BEBA89,&H00BEBA89,&H40000000,&H40000000,0,0,0,0,100,100,0,0.00,1,3,0,2,20,20,20,1
90
+
91
+ [Events]
92
+ Format: Layer, Start, End, Style, Actor, MarginL, MarginR, MarginV, Effect, Text
93
+ Dialogue: 0,0:00:01.50,0:00:03.70,Default,,0000,0000,0000,,Eine feine Testung haben sie da!
94
+ Dialogue: 0,0:00:01.50,0:00:03.70,Default,,0000,0000,0000,,¡Sí claro! Pero que lastima que no es 100% español ...
95
+ Dialogue: 0,0:00:01.50,0:00:03.70,Default,,0000,0000,0000,,Oh yeah ... 寧為太平犬,不做亂世人
96
+ EXPECTED
97
+
98
+ expect(Titlekit::ASS.export(subtitles)).to eq(expected)
99
+ end
100
+ end
101
+
102
+ describe '.build_timecode' do
103
+ it 'builds an ASS timecode from a float timecode value' do
104
+ expect(Titlekit::ASS.build_timecode(35.9678)).to eq('0:00:35.97')
105
+ end
106
+ end
107
+
108
+ describe '.parse_timecode' do
109
+ it 'obtains a float timecode value from an ASS timecode' do
110
+ expect(Titlekit::ASS.parse_timecode('0:00:35.96')).to eq(35.96)
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,55 @@
1
+ require File.join(File.expand_path(__dir__), '../spec_helper')
2
+
3
+ describe Titlekit::Job do
4
+
5
+ describe 'Automatic grouping' do
6
+
7
+ context 'with an implicit single track' do
8
+ before(:all) do
9
+ @ins = %w{one two}.map do |file|
10
+ File.join(__dir__, 'single_track', "#{file}.srt")
11
+ end
12
+ @out = File.join(__dir__, 'single_track', 'out.srt')
13
+ @expected = File.join(__dir__, 'single_track', 'expected.srt')
14
+
15
+ File.delete(@out) if File.exist?(@out)
16
+ end
17
+
18
+ it 'runs the job' do
19
+ job = Titlekit::Job.new
20
+ @ins.each { |file| job.have.file(file).encoding('UTF-8') }
21
+ job.want.file(@out)
22
+
23
+ expect(job.run).to be_true
24
+ end
25
+
26
+ it 'delivers the expected output' do
27
+ expect(FileUtils.compare_file(@out, @expected)).to be_true
28
+ end
29
+ end
30
+
31
+ context 'with implicit dual tracks' do
32
+ before(:all) do
33
+ @ins = %w{one two}.map do |file|
34
+ File.join(__dir__, 'dual_tracks', "#{file}.srt")
35
+ end
36
+ @out = File.join(__dir__, 'dual_tracks', 'out.srt')
37
+ @expected = File.join(__dir__, 'dual_tracks', 'expected.srt')
38
+
39
+ File.delete(@out) if File.exist?(@out)
40
+ end
41
+
42
+ it 'runs the job' do
43
+ job = Titlekit::Job.new
44
+ @ins.each { |file| job.have.file(file).encoding('UTF-8') }
45
+ job.want.file(@out)
46
+
47
+ expect(job.run).to be_true
48
+ end
49
+
50
+ it 'delivers the expected output' do
51
+ expect(FileUtils.compare_file(@out, @expected)).to be_true
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,15 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ <font color="#EDF393">This is a continuity of sorts</font>
4
+ <font color="#F5E665">See? Things carry over</font>
5
+
6
+ 2
7
+ 00:00:12,000 --> 00:00:20,000
8
+ <font color="#EDF393">It starts here</font>
9
+ <font color="#F5E665">I am so tired oh man</font>
10
+
11
+ 3
12
+ 00:00:22,000 --> 00:00:30,000
13
+ <font color="#EDF393">And ends there</font>
14
+ <font color="#F5E665">Writing specs is fun lololol</font>
15
+
@@ -0,0 +1,11 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ This is a continuity of sorts
4
+
5
+ 2
6
+ 00:00:12,000 --> 00:00:20,000
7
+ It starts here
8
+
9
+ 3
10
+ 00:00:22,000 --> 00:00:30,000
11
+ And ends there
@@ -0,0 +1,15 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ <font color="#EDF393">This is a continuity of sorts</font>
4
+ <font color="#F5E665">See? Things carry over</font>
5
+
6
+ 2
7
+ 00:00:12,000 --> 00:00:20,000
8
+ <font color="#EDF393">It starts here</font>
9
+ <font color="#F5E665">I am so tired oh man</font>
10
+
11
+ 3
12
+ 00:00:22,000 --> 00:00:30,000
13
+ <font color="#EDF393">And ends there</font>
14
+ <font color="#F5E665">Writing specs is fun lololol</font>
15
+
@@ -0,0 +1,11 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ See? Things carry over
4
+
5
+ 2
6
+ 00:00:12,000 --> 00:00:20,000
7
+ I am so tired oh man
8
+
9
+ 3
10
+ 00:00:22,000 --> 00:00:30,000
11
+ Writing specs is fun lololol
@@ -0,0 +1,24 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ This is a continuity of sorts
4
+
5
+ 2
6
+ 00:00:12,000 --> 00:00:20,000
7
+ It starts here
8
+
9
+ 3
10
+ 00:00:22,000 --> 00:00:30,000
11
+ And ends there
12
+
13
+ 4
14
+ 00:00:32,000 --> 00:00:40,000
15
+ See? Things carry over
16
+
17
+ 5
18
+ 00:00:42,000 --> 00:00:50,000
19
+ I am so tired oh man
20
+
21
+ 6
22
+ 00:00:52,000 --> 00:01:00,000
23
+ Writing specs is fun lololol
24
+
@@ -0,0 +1,11 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ This is a continuity of sorts
4
+
5
+ 2
6
+ 00:00:12,000 --> 00:00:20,000
7
+ It starts here
8
+
9
+ 3
10
+ 00:00:22,000 --> 00:00:30,000
11
+ And ends there
@@ -0,0 +1,24 @@
1
+ 1
2
+ 00:00:02,000 --> 00:00:10,000
3
+ This is a continuity of sorts
4
+
5
+ 2
6
+ 00:00:12,000 --> 00:00:20,000
7
+ It starts here
8
+
9
+ 3
10
+ 00:00:22,000 --> 00:00:30,000
11
+ And ends there
12
+
13
+ 4
14
+ 00:00:32,000 --> 00:00:40,000
15
+ See? Things carry over
16
+
17
+ 5
18
+ 00:00:42,000 --> 00:00:50,000
19
+ I am so tired oh man
20
+
21
+ 6
22
+ 00:00:52,000 --> 00:01:00,000
23
+ Writing specs is fun lololol
24
+
@@ -0,0 +1,11 @@
1
+ 1
2
+ 00:00:32,000 --> 00:00:40,000
3
+ See? Things carry over
4
+
5
+ 2
6
+ 00:00:42,000 --> 00:00:50,000
7
+ I am so tired oh man
8
+
9
+ 3
10
+ 00:00:52,000 --> 00:00:60,000
11
+ Writing specs is fun lololol
Binary file