Recently Written · git

subread.koplugin

KOReader plugin: the book follows the narration of an audiobook, from an .srt made by subread.space

git clone https://github.com/equwal/subread.koplugin

Log | Files | Refs


spec/srt_spec.lua (4515 bytes)

1 local Srt = require("subread.srt")
2 
3 local SAMPLE = table.concat({
4     "1",
5     "00:00:01,000 --> 00:00:03,500",
6     "It was the best of times,",
7     "",
8     "2",
9     "00:00:03,500 --> 00:00:06,000",
10     "it was the worst of times,",
11     "it was the age of wisdom,",
12     "",
13     "3",
14     "00:00:06,000 --> 00:00:08,000",
15     "\239\188\138 chapter announcement",
16     "",
17 }, "\n")
18 
19 describe("SubRead srt", function()
20     it("reads a time line with a comma", function()
21         local start, stop = Srt.parseTimeLine("00:01:02,500 --> 00:01:04,250")
22         assert.near(62.5, start, 1e-6)
23         assert.near(64.25, stop, 1e-6)
24     end)
25 
26     it("reads a time line with a full stop", function()
27         local start, stop = Srt.parseTimeLine("01:00:00.000 --> 01:00:01.000")
28         assert.near(3600, start, 1e-6)
29         assert.near(3601, stop, 1e-6)
30     end)
31 
32     it("scales the fraction by its length", function()
33         local start = Srt.parseTimeLine("00:00:00,5 --> 00:00:01,0")
34         assert.near(0.5, start, 1e-6)
35     end)
36 
37     it("rejects a line that is not a time line", function()
38         assert.is_nil(Srt.parseTimeLine("2"))
39         assert.is_nil(Srt.parseTimeLine("some cue text"))
40     end)
41 
42     it("splits CRLF, CR and LF the same way", function()
43         assert.same({ "a", "b", "c" }, Srt.splitLines("a\r\nb\rc"))
44     end)
45 
46     it("parses a whole file", function()
47         local cues = Srt.parse(SAMPLE)
48         assert.equals(3, #cues)
49         assert.near(1.0, cues[1].start, 1e-6)
50         assert.near(3.5, cues[1].stop, 1e-6)
51         assert.equals("It was the best of times,", cues[1].text)
52     end)
53 
54     it("joins the lines of a cue", function()
55         local cues = Srt.parse(SAMPLE)
56         assert.equals("it was the worst of times,\nit was the age of wisdom,",
57             cues[2].text)
58         assert.equals("it was the worst of times, it was the age of wisdom,",
59             cues[2].norm)
60     end)
61 
62     it("marks the cue that has no place in the book", function()
63         local cues = Srt.parse(SAMPLE)
64         assert.is_false(cues[1].no_place)
65         assert.is_true(cues[3].no_place)
66     end)
67 
68     it("accepts a byte order mark and CRLF", function()
69         local data = "\239\187\191" .. SAMPLE:gsub("\n", "\r\n")
70         assert.equals(3, #Srt.parse(data))
71     end)
72 
73     it("skips a block that has no time line", function()
74         local data = "header junk\n\n99\nnot a time\n\n" .. SAMPLE
75         assert.equals(3, #Srt.parse(data))
76     end)
77 
78     it("accepts a missing cue number", function()
79         local data = "00:00:01,000 --> 00:00:02,000\nfirst\n\n" ..
80                      "00:00:02,000 --> 00:00:03,000\nsecond\n"
81         local cues = Srt.parse(data)
82         assert.equals(2, #cues)
83         assert.equals("second", cues[2].text)
84     end)
85 
86     it("ends a cue on the next time line when a blank line is missing", function()
87         local data = "00:00:01,000 --> 00:00:02,000\nfirst\n" ..
88                      "00:00:02,000 --> 00:00:03,000\nsecond\n"
89         local cues = Srt.parse(data)
90         assert.equals(2, #cues)
91         assert.equals("first", cues[1].text)
92     end)
93 
94     it("drops a cue with no text", function()
95         local data = "00:00:01,000 --> 00:00:02,000\n\n" ..
96                      "00:00:02,000 --> 00:00:03,000\nkept\n"
97         local cues = Srt.parse(data)
98         assert.equals(1, #cues)
99         assert.equals("kept", cues[1].text)
100     end)
101 
102     it("sorts the cues by start time", function()
103         local data = "00:00:09,000 --> 00:00:10,000\nlate\n\n" ..
104                      "00:00:01,000 --> 00:00:02,000\nearly\n"
105         local cues = Srt.parse(data)
106         assert.equals("early", cues[1].text)
107         assert.equals("late", cues[2].text)
108     end)
109 
110     it("returns an empty list for empty input", function()
111         assert.same({}, Srt.parse(""))
112         assert.same({}, Srt.parse(nil))
113     end)
114 
115     it("keeps the start times in order for any input", function()
116         local blocks = {}
117         local seed = 7
118         for i = 1, 60 do
119             seed = (seed * 1103515245 + 12345) % 2147483648
120             local start = seed % 1000
121             blocks[#blocks + 1] = string.format(
122                 "%d\n00:00:%02d,%03d --> 00:00:%02d,%03d\ncue %d\n",
123                 i, start % 60, start % 1000, (start + 2) % 60, start % 1000, i)
124         end
125         local cues = Srt.parse(table.concat(blocks, "\n"))
126         assert.equals(60, #cues)
127         for i = 2, #cues do
128             assert.is_true(cues[i - 1].start <= cues[i].start)
129         end
130     end)
131 end)