forgot to commit in a while, colors on feed, latest releases improvements, typeset support

This commit is contained in:
ThaUnknown 2020-10-10 08:57:35 +02:00
parent 0d259c6979
commit 4826cc1863
10 changed files with 231 additions and 155 deletions

View file

@ -1,8 +1,7 @@
.custom-switch input[type=checkbox]:checked~label:after,
.custom-switch input[type=checkbox]~label:after{
transition: left .2s ease
.badge-color{
background-color: var(--color) !important;
border-color: var(--color) !important;
}
.cover-img {
object-fit: cover
}

View file

@ -214,15 +214,15 @@ video[src=""] {
}
video::cue {
background: none !important;
background: none;
font-family: var(--sub-font);
color: #fff !important;
color: #fff;
text-shadow: 2px 2px 0 #000,
2px -2px 0 #000,
-2px 2px 0 #000,
-2px -2px 0 #000,
2px 0px 0 #000,
0px 2px 0 #000,
0px 2px 0#000,
-2px 0px 0 #000,
0px -2px 0 #000,
2px 2px 2px #000;

View file

@ -15,10 +15,12 @@
<meta name="viewport" content="width=device-width" />
<title>Miru</title>
<link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.0/css/halfmoon-variables.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/halfmoon@1.1.1/css/halfmoon-variables.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="css/misc.css" rel="stylesheet">
<link href="css/player.css" rel="stylesheet">
<style id="substyles">
</style>
</head>
<body class="dark-mode with-custom-webkit-scrollbars with-custom-css-scrollbars">
@ -156,7 +158,8 @@
<span class="ts" id="upSpeed">0 B/s</span>
</div>
<div class="col d-flex justify-content-end">
<a id="dl" class="material-icons" title="Wait For File To Fully Download Before Saving To Drive">
<a id="dl" class="material-icons"
title="Wait For File To Fully Download Before Saving To Drive">
<span class="material-icons">
get_app
</span>
@ -306,7 +309,8 @@
</div>
<div class="custom-switch mb-20">
<input type="checkbox" id="subtitle2">
<label for="subtitle2">Edge Spacing [Has Issues With Displaying Multiple Subtitles At Once]</label>
<label for="subtitle2">Edge Spacing [Has Issues With Displaying Multiple Subtitles At
Once]</label>
</div>
@ -341,7 +345,7 @@
</section>
</div>
</div>
<script src="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.1.0/js/halfmoon.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.1.1/js/halfmoon.min.js"></script>
<script src="js/settingsHandler.js"></script>
<script src="js/util.js"></script>
<script src="js/animeHandler.js"></script>
@ -349,7 +353,7 @@
<script src="https://cdn.jsdelivr.net/npm/webtorrent@latest/webtorrent.min.js"></script>
<script src="js/rangeParser.js"></script>
<script src="js/torrentHandler.js"></script>
<script src="https://cdn.jsdelivr.net/npm/matroska-subtitles@3.0.1/dist/matroska-subtitles.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/matroska-subtitles@3.1.0/dist/matroska-subtitles.min.js"></script>
<script src="js/subtitleHandler.js"></script>
</body>

View file

@ -63,6 +63,7 @@ async function alRequest(a, b) {
coverImage {
extraLarge
medium
color
}
bannerImage
synonyms
@ -109,6 +110,7 @@ async function alRequest(a, b) {
coverImage {
extraLarge
medium
color
}
bannerImage
synonyms
@ -211,7 +213,7 @@ function cardCreator(media, regexParse) {
template.classList.add("card", "m-0", "p-0")
if (media) {
template.innerHTML = `
<div class="row h-full">
<div class="row h-full" style="--color:${media.coverImage.color || "#1890ff"};">
<div class="col-4">
<img src="${media.coverImage.extraLarge || ""}"
class="cover-img w-full h-full">
@ -230,7 +232,7 @@ function cardCreator(media, regexParse) {
${media.description}
</div>
<div class="px-15 pb-10 pt-5">
${media.genres.map(key => (`<span class="badge badge-pill badge-primary mt-5">${key}</span> `)).join('')}
${media.genres.map(key => (`<span class="badge badge-pill badge-color text-dark mt-5 font-weight-bold">${key}</span> `)).join('')}
</div>
</div>
</div>
@ -339,7 +341,7 @@ async function hsRss(url) {
for (let item of items) {
let i = item.querySelector.bind(item),
regexParse = eregex.exec(i("title").textContent)
if (!store[regexParse[2]] && !alResponse.data.Page.media.some(media => (Object.values(media.title).concat(media.synonyms).filter(name => name != null).includes(regexParse[2]) && ((store[regexParse[2]] = media) && true)))) {
if (!store.hasOwnProperty(regexParse[2]) && !alResponse.data.Page.media.some(media => (Object.values(media.title).concat(media.synonyms).filter(name => name != null).includes(regexParse[2]) && ((store[regexParse[2]] = media) && true)))) {
//shit not found, lookup
let res = await alRequest(regexParse[2], 1)
if(!res.data.Page.media[0]){

View file

@ -23,6 +23,7 @@ function resetVideo() {
video.remove()
nowPlayingDisplay.textContent = ""
tracks = []
headers = []
dl.removeAttribute("href")
dl.removeAttribute("download")
video = document.createElement("video")
@ -337,6 +338,7 @@ function selectLang(lang) {
for (let track of video.textTracks) {
if (track.language == lang) {
track.mode = 'showing';
parseHeader(headers[tracks.indexOf(track)])
}
else {
track.mode = 'hidden';

View file

@ -1,4 +1,5 @@
let tracks = [],
headers = [],
subtitleStream
const { SubtitleStream } = MatroskaSubtitles
@ -10,10 +11,12 @@ function parseSubs(stream) {
subtitleStream = new SubtitleStream()
subtitleStream.once('tracks', pTracks => {
pTracks.forEach(track => {
tracks[track.number] = video.addTextTrack('captions', track.type, track.language)
tracks[track.number] = video.addTextTrack('captions', track.type, track.language);
headers[track.number] = track.header;
})
if (video.textTracks[0]) {
video.textTracks[0].mode = "showing"
parseHeader(headers[3])
}
})
}
@ -26,7 +29,9 @@ function parseSubs(stream) {
const re_newline = /\\N/g, // replace \N with newline
re_softbreak = /\\n/g, // There's no equivalent function in WebVTT.
re_hardspace = /\\h/g, // Replace with &nbsp;
re_style = /\{([^}]+)\}/; // replace style
re_style = /\{([^}]+)\}/, // replace style
re_header_format = /(?<=\[V4\+? Styles\][\s\S]*Format: [^\n]*)(.+)/i,
re_header_style = /(?<=\[V4\+? Styles\][\s\S]*Style: [^\n]*)(.+)/ig;
function subConvt(result, trackNumber) {
let cue = new VTTCue(result.time / 1000, (result.time + result.duration) / 1000, ""),
text = result.text;
@ -43,92 +48,94 @@ function subConvt(result, trackNumber) {
style = style[1].split("\\"); // Get an array of override commands.
for (let j = 1; j < style.length; j++) {
// Extract the current tag name.
let tagCommand = style[j].match(/[a-zA-Z]+/)[0];
// Give special reckognition to one-letter tags.
let oneLetter = (tagCommand.length == 1) ? tagCommand : "";
// "New" position commands. It is assumed that bottom center position is the default.
if (tagCommand === "an") {
let posNum = Number(style[j].substring(2, 3));
if (Math.floor((posNum - 1) / 3) == 1) {
cue.line = 0.5;
} else if (Math.floor((posNum - 1) / 3) == 2) {
cue.line = 0;
settings.subtitle2 ? cue.text = "&nbsp;\r\n" : cue.text = ""
}
if (posNum % 3 == 1) {
cue.align = "start";
} else if (posNum % 3 == 0) {
cue.align = "end";
}
// Legacy position commands.
} else if (oneLetter === "a" && !Number.isNaN(Number(style[j].substring(1, 2)))) {
let posNum = Number(style[j].substring(1, 2));
if (posNum > 8) {
cue.line = 0.5;
} else if (posNum > 4) {
cue.line = 0;
settings.subtitle2 ? cue.text = "&nbsp;\r\n" : cue.text = ""
}
if ((posNum - 1) % 4 == 0) {
cue.align = "start";
} else if ((posNum - 1) % 4 == 2) {
cue.align = "end";
}
// Map simple text decoration commands to equivalent WebVTT text tags.
// NOTE: Strikethrough (the 's' tag) is not supported in WebVTT.
} else if (['b', 'i', 'u', 's'].includes(oneLetter)) {
if (Number(style[j].substring(1, 2)) === 0
// The more elaborate 'b-tag', which we will treat as an on-off selector.
|| (style[j].match(/b\d{3}/)
&& Number(style[j].match(/b(\d{3})/)[1]) < 500)
) {
// Closing a tag.
if (tagsToClose.includes(oneLetter)) {
// Nothing needs to be done if this tag isn't already open.
// HTML tags must be nested, so we must ensure that any tag nested inside
// the tag being closed are also closed, and then opened again once the
// current tag is closed.
while (tagsToClose.length > 0) {
let nowClosing = tagsToClose.pop();
replaceString += '</' + nowClosing + '>';
if (nowClosing !== oneLetter) {
tagsToOpen.push(nowClosing);
} else {
// There's no need to close the tags that the current tag
// is nested within.
break;
if (style[j]) {
let tagCommand = style[j].match(/[a-zA-Z]+/)[0]
// Give special reckognition to one-letter tags.
let oneLetter = (tagCommand.length == 1) ? tagCommand : "";
// "New" position commands. It is assumed that bottom center position is the default.
if (tagCommand === "an") {
let posNum = Number(style[j].substring(2, 3));
if (Math.floor((posNum - 1) / 3) == 1) {
cue.line = 0.5;
} else if (Math.floor((posNum - 1) / 3) == 2) {
cue.line = 0;
settings.subtitle2 ? cue.text = "&nbsp;\r\n" : cue.text = ""
}
if (posNum % 3 == 1) {
cue.align = "start";
} else if (posNum % 3 == 0) {
cue.align = "end";
}
// Legacy position commands.
} else if (oneLetter === "a" && !Number.isNaN(Number(style[j].substring(1, 2)))) {
let posNum = Number(style[j].substring(1, 2));
if (posNum > 8) {
cue.line = 0.5;
} else if (posNum > 4) {
cue.line = 0;
settings.subtitle2 ? cue.text = "&nbsp;\r\n" : cue.text = ""
}
if ((posNum - 1) % 4 == 0) {
cue.align = "start";
} else if ((posNum - 1) % 4 == 2) {
cue.align = "end";
}
// Map simple text decoration commands to equivalent WebVTT text tags.
// NOTE: Strikethrough (the 's' tag) is not supported in WebVTT.
} else if (['b', 'i', 'u', 's'].includes(oneLetter)) {
if (Number(style[j].substring(1, 2)) === 0
// The more elaborate 'b-tag', which we will treat as an on-off selector.
|| (style[j].match(/b\d{3}/)
&& Number(style[j].match(/b(\d{3})/)[1]) < 500)
) {
// Closing a tag.
if (tagsToClose.includes(oneLetter)) {
// Nothing needs to be done if this tag isn't already open.
// HTML tags must be nested, so we must ensure that any tag nested inside
// the tag being closed are also closed, and then opened again once the
// current tag is closed.
while (tagsToClose.length > 0) {
let nowClosing = tagsToClose.pop();
replaceString += '</' + nowClosing + '>';
if (nowClosing !== oneLetter) {
tagsToOpen.push(nowClosing);
} else {
// There's no need to close the tags that the current tag
// is nested within.
break;
}
}
}
} else {
// Opening a tag.
if (!tagsToClose.includes(oneLetter)) {
// Nothing needs to be done if the tag is already open.
// If no, place the tag on the bottom of the stack of tags being opened.
tagsToOpen.splice(0, 0, oneLetter);
}
}
} else {
// Opening a tag.
if (!tagsToClose.includes(oneLetter)) {
// Nothing needs to be done if the tag is already open.
// If no, place the tag on the bottom of the stack of tags being opened.
tagsToOpen.splice(0, 0, oneLetter);
} else if (oneLetter === 'r') {
// Resetting override tags, by closing all open tags.
// TODO: The 'r' tag can also be used to switch to a different named style,
// however, named styles haven't been implemented.
while (tagsToClose.length > 0) {
replaceString += '</' + tagsToClose.pop() + '>';
}
}
} else if (oneLetter === 'r') {
// Resetting override tags, by closing all open tags.
// TODO: The 'r' tag can also be used to switch to a different named style,
// however, named styles haven't been implemented.
while (tagsToClose.length > 0) {
replaceString += '</' + tagsToClose.pop() + '>';
// Insert open-tags for tags in the to-open list.
while (tagsToOpen.length > 0) {
let nowOpening = tagsToOpen.pop();
replaceString += '<' + nowOpening + '>';
tagsToClose.push(nowOpening);
}
}
// Insert open-tags for tags in the to-open list.
while (tagsToOpen.length > 0) {
let nowOpening = tagsToOpen.pop();
replaceString += '<' + nowOpening + '>';
tagsToClose.push(nowOpening);
}
}
}
text = text.replace(re_style, replaceString); // Replace override tag.
}
text = text.replace(re_newline, "\r\n").replace(re_softbreak, " ").replace(
re_hardspace, "&nbsp;");
let content = "<v " + result.style + ">" + text
let content = "<v." + result.style + ">" + text
while (tagsToClose.length > 0) {
content += '</' + tagsToClose.pop() + '>';
}
@ -139,4 +146,30 @@ function subConvt(result, trackNumber) {
if (!Object.values(tracks[trackNumber].cues).some(c => c.text == cue.text && c.startTime == cue.startTime && c.endTime == cue.endTime)) {
tracks[trackNumber].addCue(cue)
}
}
function parseHeader(header) {
substyles.innerHTML = ""
let format = re_header_format.exec(header)[1].split(","),
styles = header.match(re_header_style)
for (let style of styles) {
style = style.replace(/\&h/gi, "").split(",")
let bordCol
style[format.indexOf("BackColour")] ? bordCol = style[format.indexOf("BackColour")].split("").reverse().join("").slice(0, -2) : ""
substyles.innerHTML += `
video::cue(.${style[format.indexOf("Name")]}) {
color: #${style[format.indexOf("PrimaryColour")] ? style[format.indexOf("PrimaryColour")].split("").reverse().join("").slice(0, -2) : ""} !important;
text-shadow: 2px 2px 0 #${bordCol},
2px -2px 0 #${bordCol},
-2px 2px 0 #${bordCol},
-2px -2px 0 #${bordCol},
2px 0px 0 #${bordCol},
0px 2px 0 #${bordCol},
-2px 0px 0 #${bordCol},
0px -2px 0 #${bordCol},
2px 2px 2px #${bordCol};
font-weight: ${style[format.indexOf("Bold")] ? style[format.indexOf("Bold")] * -1 ? "bold" : "normal" : ""} !important;
font-style: ${style[format.indexOf("Italic")] ? style[format.indexOf("Italic")] * -1 ? "italic" : "normal" : ""} !important;
background: ${style[format.indexOf("BorderStyle")] ? style[format.indexOf("BorderStyle")] != 3 ? "none" : `#${bordCol}` : ""} !important;
}`
}
}

View file

View file

@ -1,40 +1,51 @@
'use strict';
const CACHE_NAME = 'v1.0.0';
const staticCacheName = 'v1.0.0';
const FILES_TO_CACHE = [
'offline.html',
const filesToCache = [
'index.html',
'js/settingsHandler.js',
'js/animeHandler.js',
'js/bundle.min.js',
'js/playerHandler.js',
'js/subtitleHandler.js',
'js/torrentHandler.js',
'js/rangeParser.js',
'js/util.js',
'css/misc.css',
'css/player.css',
'logo.png'
'logo.png',
'https://cdn.jsdelivr.net/npm/matroska-subtitles@3.0.1/dist/matroska-subtitles.min.js',
'https://cdn.jsdelivr.net/npm/halfmoon@1.1.0/css/halfmoon-variables.min.css',
'https://cdn.jsdelivr.net/gh/halfmoonui/halfmoon@1.1.0/js/halfmoon.min.js',
'https://cdn.jsdelivr.net/npm/webtorrent@latest/webtorrent.min.js',
'https://fonts.googleapis.com/icon?family=Material+Icons'
];
self.addEventListener('install', (evt) => {
// evt.waitUntil(
// caches.open(CACHE_NAME).then((cache) => {
// return cache.addAll(FILES_TO_CACHE);
// })
// );
self.addEventListener('install', event => {
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll(filesToCache);
})
);
self.skipWaiting();
});
self.addEventListener('activate', (evt) => {
// evt.waitUntil(
// caches.keys().then((keyList) => {
// return Promise.all(keyList.map((key) => {
// if (key !== CACHE_NAME) {
// return caches.delete(key);
// }
// }));
// })
// );
self.addEventListener('activate', event => {
const cacheWhitelist = [staticCacheName];
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheWhitelist.indexOf(cacheName) === -1) {
return caches.delete(cacheName);
}
})
);
})
);
return self.clients.claim();
});
@ -90,15 +101,22 @@ self.addEventListener('fetch', evt => {
)
})
// self.addEventListener('fetch', (evt) => {
// if (evt.request.mode !== 'navigate') {
// return;
// }
// evt.respondWith(
// fetch(evt.request)
// .catch(async () => {
// const cache = await caches.open(CACHE_NAME);
// return cache.match('offline.html');
// self.addEventListener('fetch', event => {
// event.respondWith(
// caches.match(event.request)
// .then(response => {
// if (response) {
// return response;
// }
// return fetch(event.request)
// .then(response => {
// if (response.status === 404) {
// return;
// }
// return response;
// });
// }).catch(error => {
// return caches.match('index.html');
// })
// );
// });
// });

View file

View file

@ -1,45 +1,63 @@
<?php
header("Access-Control-Allow-Origin: https://mirumoe.netlify.app");
$url = str_replace("$", "&", $_GET['url']);
if (substr($url, 0, 25) === "https://nyaa.si/?page=rss")
{
$query = explode("?page=rss", $url) [1];
if (strpos($query, '/') === false)
{
$cache_file = './cache_nyaa/' . $query;
if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 1)))
{
$file = file_get_contents($cache_file);
header('Content-Type: text/xml');
echo $file;
}
else
{
$file = file_get_contents(str_replace(" ", "+", $url));
file_put_contents($cache_file, $file, LOCK_EX);
header('Content-Type: text/xml');
echo $file;
}
$query_check = basename(realpath($query));
if ($query_check === "") {
if (strpos($query, '/') === false) {
$cache_file = './cache_nyaa/' . $query;
//echo $url.'\n';
//echo $cache_file.'\n';
if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 1)))
{
// Cache file is less than five minutes old.
// Don't bother refreshing, just use the file as-is.
$file = file_get_contents($cache_file);
header('Content-Type: text/xml');
//echo 'case fucking 1';
echo $file;
}
else
{
// Our cache is out-of-date, so load the data from our remote server,
// and also save it over our cache for next time.
$file = file_get_contents(str_replace(" ", "+", $url));
file_put_contents($cache_file, $file, LOCK_EX);
header('Content-Type: text/xml');
// echo 'case fucking 2';
echo $file;
}
}
}
}
elseif (substr($url, 0, 30) === "https://www.erai-rss.info/rss-")
{
elseif (substr($url, 0, 30) === "https://www.erai-rss.info/rss-") {
$query = explode("https://www.erai-rss.info/", $url) [1];
if (strpos($query, '/') === false)
{
$cache_file = './cache_erai/' . $query;
if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 1)))
{
$file = file_get_contents($cache_file);
header('Content-Type: text/xml');
echo $file;
}
else
{
$file = file_get_contents(str_replace(" ", "+", $url));
file_put_contents($cache_file, $file, LOCK_EX);
header('Content-Type: text/xml');
echo $file;
}
$query_check = basename(realpath($query));
if ($query_check === "") {
if (strpos($query, '/') === false) {
$cache_file = './cache_erai/' . $query;
//echo $url.'\n';
//echo $cache_file.'\n';
if (file_exists($cache_file) && (filemtime($cache_file) > (time() - 60 * 1))) {
// Cache file is less than five minutes old.
// Don't bother refreshing, just use the file as-is.
$file = file_get_contents($cache_file);
header('Content-Type: text/xml');
//echo 'case fucking 1';
echo $file;
}
else {
// Our cache is out-of-date, so load the data from our remote server,
// and also save it over our cache for next time.
$file = file_get_contents(str_replace(" ", "+", $url));
file_put_contents($cache_file, $file, LOCK_EX);
header('Content-Type: text/xml');
// echo 'case fucking 2';
echo $file;
}
}
}
}
?>