spec/languages_spec.lua (3952 bytes)
1 -- The languages SubRead is checked against: English, Portuguese, Spanish, 2 -- Russian and Japanese. The cue text of each has to survive the pure Lua 3 -- modules unchanged: the search in the book uses it byte for byte. 4 5 local Text = require("subread.text") 6 local Srt = require("subread.srt") 7 local Cues = require("subread.cues") 8 9 -- One line of a book in each language, with the marks that its books use. 10 local LINES = { 11 en = "It was a dark night; the rain fell on the yellow wallpaper.", 12 pt = "— Não me parece bonito — disse ela, à porta do coração.", 13 es = "¿Qué es esto? ¡Ñandú, señor Quijote, en la defensa de la dueña!", 14 ru = "«Ёлка, — сказал он, — и её огни горят в ожидании заказа».", 15 ja = "「女のいない男たち」東京で暮らしている。吾輩は猫である。", 16 } 17 -- Characters in each line, counted by hand. 18 local CHARS = { en = 59, pt = 55, es = 63, ru = 57, ja = 28 } 19 local ORDER = { "en", "pt", "es", "ru", "ja" } 20 21 local function srtOf() 22 local blocks = {} 23 for i, code in ipairs(ORDER) do 24 blocks[#blocks + 1] = string.format("%d\n00:00:%02d,000 --> 00:00:%02d,900\n%s\n", 25 i, i, i, LINES[code]) 26 end 27 return table.concat(blocks, "\n") 28 end 29 30 describe("SubRead languages", function() 31 it("counts the characters of each script", function() 32 for code, line in pairs(LINES) do 33 assert.equals(CHARS[code], Text.len(line)) 34 end 35 end) 36 37 it("keeps a normalised line byte for byte", function() 38 for _, line in pairs(LINES) do 39 assert.equals(line, Text.normalize(line)) 40 assert.equals(line, Text.sub(line, 1, Text.len(line))) 41 end 42 end) 43 44 it("turns the ideographic space of Japanese into one space", function() 45 assert.equals("a b", Text.normalize("a\227\128\128b")) 46 assert.equals("「女のいない男たち」 東京", Text.normalize("「女のいない男たち」 東京")) 47 end) 48 49 it("cuts anchors and tails on character boundaries in each script", function() 50 for code, line in pairs(LINES) do 51 local anchors = Text.anchors(line) 52 assert.equals(2, #anchors, code) 53 assert.equals(24, Text.len(anchors[1]), code) 54 assert.equals(12, Text.len(anchors[2]), code) 55 assert.equals(anchors[1], Text.sub(line, 1, 24), code) 56 local tail = Text.tail(line) 57 assert.equals(12, Text.len(tail), code) 58 assert.equals(tail, Text.sub(line, Text.len(line) - 11, Text.len(line)), code) 59 end 60 end) 61 62 it("reads a subtitle file that mixes the scripts", function() 63 local cues = Srt.parse(srtOf()) 64 assert.equals(#ORDER, #cues) 65 for i, code in ipairs(ORDER) do 66 assert.equals(LINES[code], cues[i].text) 67 assert.equals(LINES[code], cues[i].norm) 68 assert.is_false(cues[i].no_place) 69 assert.near(i, cues[i].start, 1e-6) 70 end 71 end) 72 73 it("finds the cue of a page in each script", function() 74 local index = Cues.new(Srt.parse(srtOf())) 75 for i, code in ipairs(ORDER) do 76 -- The page starts a few characters into the line, as a page often does. 77 local page = Text.sub(LINES[code], 3, Text.len(LINES[code])) .. " and more text of the page" 78 assert.equals(i, index:findIndexForText(page), code) 79 -- A selection of a few words in the middle of the line. 80 local selected = Text.sub(LINES[code], 8, 19) 81 assert.equals(i, index:findIndexContaining(Text.normalize(selected)), code) 82 end 83 end) 84 85 it("ellipsizes on a character boundary", function() 86 for _, line in pairs(LINES) do 87 local short = Text.ellipsize(line, 10) 88 assert.equals(11, Text.len(short)) 89 assert.equals(Text.sub(line, 1, 10), Text.sub(short, 1, 10)) 90 end 91 end) 92 end)