// ==UserScript==
// @name Bilibili 轴Man小助手
// @namespace http://tampermonkey.net/
// @version 0.7
// @description 将评论区的轴转换至Bilibili的笔记,实现手机可点的特性
// @author as042971
// @include *://www.bilibili.com/video/av*
// @include *://www.bilibili.com/video/BV*
// @license MIT
// @grant none
// @esversion 8
// @downloadURL none
// ==/UserScript==
(function() {
'use strict';
// 设置 useIndent = true 会在文本前增加缩进和引导线
const useIndent = true;
// 设置 useNewLine = true 会在文本后增加空行
const useNewLine = false;
const wait1s = function () {
return new Promise(resolve => {
setTimeout(() => {
resolve();
}, 1000);
});
};
const waitforComponent = async function(name) {
while (true) {
let component = document.querySelector(name);
if (component) {
return component;
}
await wait1s();
}
}
const markTime = async function (loc, time) {
window.player.seek(time);
document.querySelector('.ql-tag-btn').click();
await wait1s();
// 人工将时间戳置底
let editor = document.querySelector('.ql-editor');
editor.appendChild(editor.childNodes[loc]);
// 清除多出来的那一个
editor.removeChild(editor.childNodes[loc]);
};
const insertText = function (text, guide) {
let editor = document.querySelector('.ql-editor');
let insertItem = document.createElement('p');
if (text.charAt(text.length-1) == '*') {
text = ''+ text.substr(0, text.length - 1) +'';
}
if (useIndent) {
if (guide) {
text = ' └─ ' + text;
} else {
text = ' ' + text;
}
}
insertItem.innerHTML = text;
editor.appendChild(insertItem);
};
const insertNewLine = function () {
let editor = document.querySelector('.ql-editor');
let insertItem = document.createElement('p');
editor.appendChild(insertItem);
};
const parseTime = function (timeStr) {
const timePart = timeStr.split(":");
if (timePart.length == 3) {
return parseInt(timePart[0]) * 3600 + parseInt(timePart[1]) * 60 + parseInt(timePart[2]);
} else {
return parseInt(timePart[0]) * 60 + parseInt(timePart[1]);
}
};
const handleTimeline = async function (inputStr) {
let editor = document.querySelector('.ql-editor');
const loc = editor.childNodes.length - 1;
// h:mm:ss 型时间
const timeRegex = /^(\d{1})\:([0-5]{1}\d{1})\:([0-5]{1}\d{1})$/;
// mm:ss 型时间
const timeRegex2 = /^([0-5]{1}\d{1})\:([0-5]{1}\d{1})$/;
// 通过换行分隔
const inputStrList = inputStr.split(/[(\r\n)\r\n]+/);
for (let i = 0; i < inputStrList.length; i++) {
let inputStrItem = inputStrList[i];
let nonTimeStr = '';
let time = 0;
// 通过空格分隔
const inputPart = inputStrItem.split(' ');
for (let j = 0; j < inputPart.length; j++) {
let part = inputPart[j];
if (part) {
if (timeRegex.test(part) || timeRegex2.test(part)) {
// 这是一个时间戳
// 结束上一次的非时间戳内容
if (nonTimeStr != '') {
if (time != 0) {
await markTime(loc, time);
insertText(nonTimeStr, true);
time = 0;
} else {
insertText(nonTimeStr, false);
}
if (useNewLine) {
insertNewLine();
}
nonTimeStr = '';
}
// 标记这个时间戳
time = parseTime(part);
} else {
if (nonTimeStr != '') {
nonTimeStr += ' ';
}
nonTimeStr += part;
}
}
}
if (nonTimeStr != '') {
if (time != 0) {
await markTime(loc, time);
insertText(nonTimeStr, true);
time = 0;
} else {
insertText(nonTimeStr, false);
}
if (useNewLine) {
insertNewLine('');
}
}
}
};
const inject = function(node) {
let rawTimeline = document.createElement('textarea');
rawTimeline.setAttribute('id', 'inject-timeline');
rawTimeline.setAttribute('class', 'ipt-txt');
rawTimeline.setAttribute('rows', '1');
rawTimeline.oninput = async function () {
let data = rawTimeline.value;
rawTimeline.value = "";
rawTimeline.setAttribute('disabled', 'disabled');
rawTimeline.setAttribute('placeholder', '处理中,请稍后...');
await handleTimeline(data);
rawTimeline.removeAttribute('disabled');
rawTimeline.setAttribute('placeholder', '处理完毕,请换P(并将光标移至文末空行)或直接发表');
};
node.insertBefore(rawTimeline, node.childNodes[3]);
rawTimeline.setAttribute('placeholder', '将光标移动至文末空行后,将轴粘贴至这里...');
};
let app = document.getElementById('app');
let observerOptions = {
childList: true,
attributes: false,
subtree: false
};
let observer = new MutationObserver((mutation_records) => {
let note = document.querySelector('.active-note');
if (note) {
inject(note);
observer.disconnect();
}
});
observer.observe(app, observerOptions);
})();