lrcReader[typing-tube.net]

Add buttons to load the .lrc format file on the edit screen on typing-tube.net.

  1. // ==UserScript==
  2. // @name lrcReader[typing-tube.net]
  3. // @namespace http://tampermonkey.net/lrcReader
  4. // @version 0.45
  5. // @description Add buttons to load the .lrc format file on the edit screen on typing-tube.net.
  6. // @author Spacia
  7. // @match https://typing-tube.net/movie/edit?videoid=*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. //Greasy Fork https://greasyfork.org/ja/scripts/391474-realtimecombatting-typing-tube
  12.  
  13. //This is the Entry point.
  14. (function() {
  15. 'use strict';
  16.  
  17. AddLrcReaderElements();
  18.  
  19. })();
  20.  
  21. //--------------------------------------------------------------
  22. function AddLrcReaderElements(){
  23.  
  24. // Add a div element to be container to the bottom of the navigation menu "edit".
  25. var elDiv = document.createElement("div");
  26. elDiv.classList.add('row');
  27. elDiv.classList.add('ml-2');
  28. elDiv.classList.add('w-100');
  29. elDiv.id = "ContainerOflrcReader";
  30. var elEdit = document.getElementById("edit");
  31. elEdit.appendChild(elDiv);
  32. var elDevId = document.getElementById("ContainerOflrcReader");
  33.  
  34. // Add a button for uploading .lrc format file in container created by former code.
  35. var elTextDiv = document.createElement("div");
  36. elTextDiv.classList.add("col-4");
  37. elTextDiv.innerHTML = "lrcファイルを参照";
  38. elDevId.appendChild(elTextDiv);
  39.  
  40. var elForm = document.createElement("form");
  41. elForm.classList.add("col-6");
  42. elForm.innerHTML = "<div><input name='lrcFile' type='file' accept='.lrc'></div>";
  43. elForm.addEventListener('change', onLoadLrc);
  44. elDevId.appendChild(elForm);
  45.  
  46.  
  47. // Add a div element to be container to the bottom of the navigation menu "edit".
  48. var elDiv2 = document.createElement("div");
  49. elDiv2.classList.add('row');
  50. elDiv2.classList.add('ml-2');
  51. elDiv2.classList.add('w-100');
  52. elDiv2.id = "ContainerOflrcReader2";
  53. elEdit.appendChild(elDiv2);
  54.  
  55. // Add a button for uploading .lrc format file in container created by former code.
  56. var elTextDiv2 = document.createElement("div");
  57. elTextDiv2.classList.add("col-4");
  58. elTextDiv2.innerHTML = "replファイルを参照";
  59. elDiv2.appendChild(elTextDiv2);
  60.  
  61. var elForm2 = document.createElement("form");
  62. elForm2.classList.add("col-6");
  63. elForm2.innerHTML = "<div><input name='replFile' type='file' accept='.repl.txt'></div>";
  64. elForm2.addEventListener('change', onLoadRepl);
  65. elDiv2.appendChild(elForm2);
  66.  
  67. // Add a div element to be container to the bottom of the navigation menu "edit".
  68. var elDiv3 = document.createElement("div");
  69. elDiv3.classList.add('row');
  70. elDiv3.classList.add('ml-2');
  71. elDiv3.classList.add('w-100');
  72. elDiv3.id = "ContainerOflrcReader2";
  73. elEdit.appendChild(elDiv3);
  74.  
  75. // Add radio buttons to select English or Kana.
  76. var elForm3 = document.createElement("form");
  77. elForm3.classList.add("col-4");
  78. //> @note rewrite 2020/08/12 ---------
  79. elForm3.innerHTML = "<span style='padding-right:20px;'><label><input id='lrcConverTypeKana' name='lrcConvertType' type='radio' value='kana' checked>かな </label></span>"
  80. + "<span><label><input id='lrcConverTypeEng' name='lrcConvertType' type='radio' value='eng'>英語(旧環境 削除予定)</label></span>"
  81. +"<span><label><input id='lrcConverTypeCopy' name='lrcConvertType' type='radio' value='copy'>丸コピ</label></span>";
  82. //> @note end ---------
  83. elDiv3.appendChild(elForm3);
  84.  
  85. var elDiv4 = document.createElement("div");
  86. elDiv4.classList.add('row');
  87. elDiv4.classList.add('ml-2');
  88. elDiv4.classList.add('w-100');
  89. elDiv4.id = "ContainerOflrcReader2";
  90. elEdit.appendChild(elDiv4);
  91.  
  92. var btStart = document.createElement("input");
  93. btStart.id = "LRstart";
  94. btStart.setAttribute("type","button");
  95. btStart.setAttribute("value","lrcファイルの読み込みを開始!");
  96. btStart.setAttribute("style","margin:4px 4px");
  97. btStart.disabled = true;
  98. btStart.addEventListener("click", start);
  99. elDiv4.appendChild(btStart);
  100.  
  101.  
  102. }
  103. var _file;
  104. var fr;
  105. //--------------------------------------------------------------
  106.  
  107. function onLoadLrc(event){
  108. _file = event.target.files[0];
  109.  
  110. document.getElementById("LRstart").disabled = (_file == null);
  111.  
  112. if(_file != null){
  113.  
  114. fr = new FileReader();
  115. fr.onload = function(e) {
  116. // A file was loaded.
  117. SetLinesOfLyricsToTimelineTable(fr.result.split('\n'));
  118. }
  119. }
  120. }
  121.  
  122. var mapOfRuby = {};
  123. //--------------------------------------------------------------
  124. function onLoadRepl(event){
  125. var _file = event.target.files[0];
  126.  
  127. if(_file != null){
  128. var fr = new FileReader();
  129. fr.onload = function(e) {
  130. // A file was loaded.
  131. var listOfRuby = fr.result.split('\n');
  132. mapOfRuby = {};
  133. listOfRuby.forEach((ruby) => {
  134. var val = ruby.match(/,[^,]*$/)[0].replace(",", "").replace("\"", "");
  135. var key = ruby.match(/^[^,]*,/)[0].replace(",", "").replace("\"", "");
  136. // console.log(key);
  137. // console.log(val);
  138. mapOfRuby[key] = val;
  139. });
  140. }
  141. fr.readAsText(_file);
  142. }
  143. }
  144.  
  145. //--------------------------------------------------------------
  146. function start(){
  147. SetTimeEvent();
  148. //> @note rewrite 2020/08/12 ---------
  149. document.getElementById("LRstart").disabled = (true);
  150. //> @note end ---------
  151.  
  152. if(fr){
  153. fr.readAsText(_file);
  154. }else{
  155. alert("Failed to load file formated .lrc");
  156. }
  157. }
  158.  
  159. //> @note rewrite 2020/08/12 ---------
  160. var loadMode; //mode type 'kana or eng or copy'
  161. var lineidx = 0;
  162. var time;
  163. var editedLine;
  164. var lines;
  165. var timeEventFlag;
  166.  
  167. function SetTimeEvent(){
  168.  
  169. setTimeout(() => {
  170. if(document.getElementById("kana").value.length != 0){
  171. Clock_AddTimeTable();
  172. }
  173. if(timeEventFlag){
  174. SetTimeEvent();
  175. }
  176. }, 20);
  177.  
  178. }
  179.  
  180. //--------------------------------------------------------------
  181. function SetLinesOfLyricsToTimelineTable(_lines) {
  182.  
  183. //> @note rewrite 2020/08/12 ---------
  184. if(document.getElementById('lrcConverTypeKana').checked){
  185. loadMode = 'kana';
  186. } else if(document.getElementById('lrcConverTypeEng').checked){
  187. loadMode = 'eng';
  188. }else{
  189. loadMode = 'copy';
  190. }
  191. //> @note end
  192. lineidx = 0;
  193. lines = _lines;
  194. timeEventFlag = true;
  195.  
  196. retriveLineInfo();
  197. }
  198.  
  199.  
  200. //--------------------------------------------------------------
  201. function retriveLineInfo(){
  202.  
  203. var line = lines[lineidx++];
  204.  
  205. var ptnsOfTimeTag = [
  206.  /\[\d\d:\d\d:\d\d\]/g,
  207. /\[\d\d:\d\d.\d\d\]/g,
  208. /\[\d\d:\d\d]/g
  209. ];
  210.  
  211. //if empty line then check next line.
  212. var isEmpty = true;
  213. var isCsOmitted = false;
  214. ptnsOfTimeTag.forEach(function(ptn, idx){
  215. if(ptn.test(line) == true){
  216. isEmpty = false;
  217. if(idx == 2){
  218. isCsOmitted = true;
  219. }
  220. }
  221. });
  222. if(isEmpty){
  223. if(lineidx < lines.length){
  224. retriveLineInfo();
  225. }else{
  226. timeEventFlag = false;
  227. addRuby();
  228. }
  229. return;
  230. }
  231.  
  232.  
  233. //get time for this line.
  234. var ptnOfTwoDigidTime = /\d\d/g;
  235. var timesStr = line.match(ptnOfTwoDigidTime);
  236. var minute = parseFloat(timesStr[0]);
  237. var second = parseFloat(timesStr[1]);
  238. var centiSec = 0;
  239. if(!isCsOmitted){
  240. centiSec = parseFloat(timesStr[2]);
  241. }
  242. time = minute * 60 + second + centiSec * 0.01;
  243. //console.log(time);
  244.  
  245. //get line of text.
  246. editedLine = line;
  247. ptnsOfTimeTag.forEach(function(ptn, idx){
  248. editedLine = editedLine.replace(ptn,"").trim();
  249. });
  250. //console.log(editedLine);
  251.  
  252. //Add time and lineLyrics to the timeline Table in the navigation menu "edit".
  253. document.getElementById("time").value = time;
  254. document.getElementById("words").value = editedLine;
  255.  
  256. //空行なら変換の必要なし。タイムテーブルにそのまま追加
  257. if(editedLine.length == 0){
  258. Clock_AddTimeTable(true);
  259. return;
  260. }
  261.  
  262. //> @note rewrite 2020/08/12 ---------
  263. if(loadMode == 'kana'){
  264. command_kakasi();
  265. }else if(loadMode == 'eng'){
  266. command_kakasi_en();
  267. }else{
  268. document.getElementById("kana").value = editedLine;
  269. }
  270. //> @note end
  271. }
  272.  
  273.  
  274. //--------------------------------------------------------------
  275. function Clock_AddTimeTable(isEmptyLine = false){
  276. if(isEmptyLine || document.getElementById("kana").value.length != 0){
  277. command_add();
  278. if(lineidx < lines.length){
  279. retriveLineInfo();
  280. }else{
  281. timeEventFlag = false;
  282. addRuby();
  283. }
  284. }
  285. }
  286.  
  287.  
  288. //--------------------------------------------------------------
  289. function addRuby(){
  290.  
  291. // console.log(mapOfRuby);
  292.  
  293. var DOMTbody = document.querySelector("#subtitles_table > tbody");
  294. var DOMlines = DOMTbody.children;
  295. console.log(DOMlines);
  296. for (var i = 0; i < DOMlines.length; i++) {
  297. //<ruby>タグを追加
  298. DOMlines[i].children[1].innerHTML = replaceRuby(DOMlines[i].children[1].innerHTML);
  299. }
  300.  
  301. }
  302.  
  303. //--------------------------------------------------------------
  304. function replaceRuby(str){
  305.  
  306. //二重に追加されてしまうのを防止するため、文字数が多い順に追加。
  307. for(var i = 20;i > 0;--i){
  308. Object.keys(mapOfRuby).forEach(function(key){
  309. if(key.length == i){
  310. var val = this[key];
  311. // if(new RegExp("<ruby>?!<\/ruby\/>*" + key + "?!<ruby>*<\/ruby>").test(val)){
  312. str = str.replace(key, "<ruby>" + key + "<rt>" + val + "</rt></ruby>");
  313. }
  314. }, mapOfRuby);
  315. }
  316. return str;
  317. }