fix mobile UI + MAYBE direct tidal.com querying for pages functions???
This commit is contained in:
parent
fdb13d4a1c
commit
0255bffdd1
7 changed files with 320 additions and 300 deletions
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(grep:*)",
|
||||||
|
"Bash(find /c/Users/Admin/Documents/GitHub/monochrome -type f \\\\\\(-name *.html -o -name index.html \\\\\\))",
|
||||||
|
"Bash(xargs wc:*)"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,50 @@
|
||||||
// functions/album/[id].js
|
// functions/album/[id].js
|
||||||
|
|
||||||
|
class TidalAPI {
|
||||||
|
static CLIENT_ID = 'txNoH4kkV41MfH25';
|
||||||
|
static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98=';
|
||||||
|
|
||||||
|
async getToken() {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
client_id: TidalAPI.CLIENT_ID,
|
||||||
|
client_secret: TidalAPI.CLIENT_SECRET,
|
||||||
|
grant_type: 'client_credentials',
|
||||||
|
});
|
||||||
|
const res = await fetch('https://auth.tidal.com/v1/oauth2/token', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`),
|
||||||
|
},
|
||||||
|
body: params,
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchJson(url, params = {}) {
|
||||||
|
const token = await this.getToken();
|
||||||
|
const u = new URL(url);
|
||||||
|
Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v)));
|
||||||
|
const res = await fetch(u.toString(), {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Tidal API error: ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAlbumMetadata(id) {
|
||||||
|
return await this.fetchJson(`https://api.tidal.com/v1/albums/${id}`, { countryCode: 'US' });
|
||||||
|
}
|
||||||
|
|
||||||
|
getCoverUrl(id, size = '1280') {
|
||||||
|
if (!id) return '';
|
||||||
|
const formattedId = String(id).replace(/-/g, '/');
|
||||||
|
return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ServerAPI {
|
class ServerAPI {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.INSTANCES_URLS = [
|
this.INSTANCES_URLS = [
|
||||||
|
|
@ -96,13 +141,26 @@ export async function onRequest(context) {
|
||||||
const albumId = params.id;
|
const albumId = params.id;
|
||||||
|
|
||||||
if (isBot && albumId) {
|
if (isBot && albumId) {
|
||||||
|
let api;
|
||||||
|
let album;
|
||||||
|
let tracks = [];
|
||||||
try {
|
try {
|
||||||
const api = new ServerAPI();
|
api = new TidalAPI();
|
||||||
|
album = await api.getAlbumMetadata(albumId);
|
||||||
|
} catch (directError) {
|
||||||
|
console.warn(`Direct Tidal API failed for album ${albumId}, falling back to proxies:`, directError);
|
||||||
|
try {
|
||||||
|
api = new ServerAPI();
|
||||||
const data = await api.getAlbumMetadata(albumId);
|
const data = await api.getAlbumMetadata(albumId);
|
||||||
const album = data.data || data.album || data;
|
album = data.data || data.album || data;
|
||||||
const tracks = album.items || data.tracks || [];
|
tracks = album.items || data.tracks || [];
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error(`All methods failed for album ${albumId}:`, fallbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (album && (album.title || album.name)) {
|
if (album && (album.title || album.name)) {
|
||||||
|
try {
|
||||||
const title = album.title || album.name;
|
const title = album.title || album.name;
|
||||||
const artist = album.artist?.name || 'Unknown Artist';
|
const artist = album.artist?.name || 'Unknown Artist';
|
||||||
const year = album.releaseDate ? new Date(album.releaseDate).getFullYear() : '';
|
const year = album.releaseDate ? new Date(album.releaseDate).getFullYear() : '';
|
||||||
|
|
@ -146,9 +204,9 @@ export async function onRequest(context) {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
|
return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error for album ${albumId}:`, error);
|
console.error(`Error generating meta tags for album ${albumId}:`, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,50 @@
|
||||||
// functions/artist/[id].js
|
// functions/artist/[id].js
|
||||||
|
|
||||||
|
class TidalAPI {
|
||||||
|
static CLIENT_ID = 'txNoH4kkV41MfH25';
|
||||||
|
static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98=';
|
||||||
|
|
||||||
|
async getToken() {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
client_id: TidalAPI.CLIENT_ID,
|
||||||
|
client_secret: TidalAPI.CLIENT_SECRET,
|
||||||
|
grant_type: 'client_credentials',
|
||||||
|
});
|
||||||
|
const res = await fetch('https://auth.tidal.com/v1/oauth2/token', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`),
|
||||||
|
},
|
||||||
|
body: params,
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchJson(url, params = {}) {
|
||||||
|
const token = await this.getToken();
|
||||||
|
const u = new URL(url);
|
||||||
|
Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v)));
|
||||||
|
const res = await fetch(u.toString(), {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Tidal API error: ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getArtistMetadata(id) {
|
||||||
|
return await this.fetchJson(`https://api.tidal.com/v1/artists/${id}`, { countryCode: 'US' });
|
||||||
|
}
|
||||||
|
|
||||||
|
getArtistPictureUrl(id, size = '750') {
|
||||||
|
if (!id) return '';
|
||||||
|
const formattedId = id.replace(/-/g, '/');
|
||||||
|
return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ServerAPI {
|
class ServerAPI {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.INSTANCES_URLS = [
|
this.INSTANCES_URLS = [
|
||||||
|
|
@ -96,12 +141,24 @@ export async function onRequest(context) {
|
||||||
const artistId = params.id;
|
const artistId = params.id;
|
||||||
|
|
||||||
if (isBot && artistId) {
|
if (isBot && artistId) {
|
||||||
|
let api;
|
||||||
|
let artist;
|
||||||
try {
|
try {
|
||||||
const api = new ServerAPI();
|
api = new TidalAPI();
|
||||||
|
artist = await api.getArtistMetadata(artistId);
|
||||||
|
} catch (directError) {
|
||||||
|
console.warn(`Direct Tidal API failed for artist ${artistId}, falling back to proxies:`, directError);
|
||||||
|
try {
|
||||||
|
api = new ServerAPI();
|
||||||
const data = await api.getArtistMetadata(artistId);
|
const data = await api.getArtistMetadata(artistId);
|
||||||
const artist = data.artist || data.data || data;
|
artist = data.artist || data.data || data;
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error(`All methods failed for artist ${artistId}:`, fallbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (artist && (artist.name || artist.title)) {
|
if (artist && (artist.name || artist.title)) {
|
||||||
|
try {
|
||||||
const name = artist.name || artist.title;
|
const name = artist.name || artist.title;
|
||||||
const description = `Listen to ${name} on Monochrome`;
|
const description = `Listen to ${name} on Monochrome`;
|
||||||
const imageUrl = artist.picture
|
const imageUrl = artist.picture
|
||||||
|
|
@ -138,9 +195,9 @@ export async function onRequest(context) {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
|
return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error for artist ${artistId}:`, error);
|
console.error(`Error generating meta tags for artist ${artistId}:`, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,50 @@
|
||||||
// functions/playlist/[id].js
|
// functions/playlist/[id].js
|
||||||
|
|
||||||
|
class TidalAPI {
|
||||||
|
static CLIENT_ID = 'txNoH4kkV41MfH25';
|
||||||
|
static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98=';
|
||||||
|
|
||||||
|
async getToken() {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
client_id: TidalAPI.CLIENT_ID,
|
||||||
|
client_secret: TidalAPI.CLIENT_SECRET,
|
||||||
|
grant_type: 'client_credentials',
|
||||||
|
});
|
||||||
|
const res = await fetch('https://auth.tidal.com/v1/oauth2/token', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`),
|
||||||
|
},
|
||||||
|
body: params,
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchJson(url, params = {}) {
|
||||||
|
const token = await this.getToken();
|
||||||
|
const u = new URL(url);
|
||||||
|
Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v)));
|
||||||
|
const res = await fetch(u.toString(), {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Tidal API error: ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPlaylistMetadata(id) {
|
||||||
|
return await this.fetchJson(`https://api.tidal.com/v1/playlists/${id}`, { countryCode: 'US' });
|
||||||
|
}
|
||||||
|
|
||||||
|
getCoverUrl(id, size = '1080') {
|
||||||
|
if (!id) return '';
|
||||||
|
const formattedId = String(id).replace(/-/g, '/');
|
||||||
|
return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ServerAPI {
|
class ServerAPI {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.INSTANCES_URLS = [
|
this.INSTANCES_URLS = [
|
||||||
|
|
@ -75,7 +120,6 @@ class ServerAPI {
|
||||||
const response = await this.fetchWithRetry(`/playlist/${id}`);
|
const response = await this.fetchWithRetry(`/playlist/${id}`);
|
||||||
return await response.json();
|
return await response.json();
|
||||||
} catch {
|
} catch {
|
||||||
// Fallback to query param style
|
|
||||||
const response = await this.fetchWithRetry(`/playlist?id=${id}`);
|
const response = await this.fetchWithRetry(`/playlist?id=${id}`);
|
||||||
return await response.json();
|
return await response.json();
|
||||||
}
|
}
|
||||||
|
|
@ -97,12 +141,24 @@ export async function onRequest(context) {
|
||||||
const playlistId = params.id;
|
const playlistId = params.id;
|
||||||
|
|
||||||
if (isBot && playlistId) {
|
if (isBot && playlistId) {
|
||||||
|
let api;
|
||||||
|
let playlist;
|
||||||
try {
|
try {
|
||||||
const api = new ServerAPI();
|
api = new TidalAPI();
|
||||||
|
playlist = await api.getPlaylistMetadata(playlistId);
|
||||||
|
} catch (directError) {
|
||||||
|
console.warn(`Direct Tidal API failed for playlist ${playlistId}, falling back to proxies:`, directError);
|
||||||
|
try {
|
||||||
|
api = new ServerAPI();
|
||||||
const data = await api.getPlaylistMetadata(playlistId);
|
const data = await api.getPlaylistMetadata(playlistId);
|
||||||
const playlist = data.playlist || data.data || data;
|
playlist = data.playlist || data.data || data;
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error(`All methods failed for playlist ${playlistId}:`, fallbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (playlist && (playlist.title || playlist.name)) {
|
if (playlist && (playlist.title || playlist.name)) {
|
||||||
|
try {
|
||||||
const title = playlist.title || playlist.name;
|
const title = playlist.title || playlist.name;
|
||||||
const trackCount = playlist.numberOfTracks;
|
const trackCount = playlist.numberOfTracks;
|
||||||
const description = `Playlist • ${trackCount} Tracks\nListen on Monochrome`;
|
const description = `Playlist • ${trackCount} Tracks\nListen on Monochrome`;
|
||||||
|
|
@ -143,9 +199,9 @@ export async function onRequest(context) {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
|
return new Response(metaHtml, { headers: { 'content-type': 'text/html;charset=UTF-8' } });
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error for playlist ${playlistId}:`, error);
|
console.error(`Error generating meta tags for playlist ${playlistId}:`, error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,61 @@ function getTrackArtists(track = {}, { fallback = 'Unknown Artist' } = {}) {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TidalAPI {
|
||||||
|
static CLIENT_ID = 'txNoH4kkV41MfH25';
|
||||||
|
static CLIENT_SECRET = 'dQjy0MinCEvxi1O4UmxvxWnDjt4cgHBPw8ll6nYBk98=';
|
||||||
|
|
||||||
|
async getToken() {
|
||||||
|
const params = new URLSearchParams({
|
||||||
|
client_id: TidalAPI.CLIENT_ID,
|
||||||
|
client_secret: TidalAPI.CLIENT_SECRET,
|
||||||
|
grant_type: 'client_credentials',
|
||||||
|
});
|
||||||
|
const res = await fetch('https://auth.tidal.com/v1/oauth2/token', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
Authorization: 'Basic ' + btoa(`${TidalAPI.CLIENT_ID}:${TidalAPI.CLIENT_SECRET}`),
|
||||||
|
},
|
||||||
|
body: params,
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Token request failed: ${res.status}`);
|
||||||
|
const data = await res.json();
|
||||||
|
return data.access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchJson(url, params = {}) {
|
||||||
|
const token = await this.getToken();
|
||||||
|
const u = new URL(url);
|
||||||
|
Object.entries(params).forEach(([k, v]) => u.searchParams.set(k, String(v)));
|
||||||
|
const res = await fetch(u.toString(), {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
});
|
||||||
|
if (!res.ok) throw new Error(`Tidal API error: ${res.status}`);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTrackMetadata(id) {
|
||||||
|
return await this.fetchJson(`https://api.tidal.com/v1/tracks/${id}/`, { countryCode: 'US' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async getStreamUrl(id) {
|
||||||
|
const data = await this.fetchJson(`https://api.tidal.com/v1/tracks/${id}/playbackinfo`, {
|
||||||
|
audioquality: 'LOW',
|
||||||
|
playbackmode: 'STREAM',
|
||||||
|
assetpresentation: 'FULL',
|
||||||
|
countryCode: 'US',
|
||||||
|
});
|
||||||
|
return data.url || data.streamUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCoverUrl(id, size = '1280') {
|
||||||
|
if (!id) return '';
|
||||||
|
const formattedId = String(id).replace(/-/g, '/');
|
||||||
|
return `https://resources.tidal.com/images/${formattedId}/${size}x${size}.jpg`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ServerAPI {
|
class ServerAPI {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.INSTANCES_URLS = [
|
this.INSTANCES_URLS = [
|
||||||
|
|
@ -116,11 +171,24 @@ export async function onRequest(context) {
|
||||||
const trackId = params.id;
|
const trackId = params.id;
|
||||||
|
|
||||||
if (isBot && trackId) {
|
if (isBot && trackId) {
|
||||||
|
// Try direct Tidal API first, fall back to proxy instances
|
||||||
|
let api;
|
||||||
|
let track;
|
||||||
try {
|
try {
|
||||||
const api = new ServerAPI();
|
api = new TidalAPI();
|
||||||
const track = await api.getTrackMetadata(trackId);
|
track = await api.getTrackMetadata(trackId);
|
||||||
|
} catch (directError) {
|
||||||
|
console.warn(`Direct Tidal API failed for track ${trackId}, falling back to proxies:`, directError);
|
||||||
|
try {
|
||||||
|
api = new ServerAPI();
|
||||||
|
track = await api.getTrackMetadata(trackId);
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error(`All methods failed for track ${trackId}:`, fallbackError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (track) {
|
if (track) {
|
||||||
|
try {
|
||||||
const title = getTrackTitle(track);
|
const title = getTrackTitle(track);
|
||||||
const artist = getTrackArtists(track);
|
const artist = getTrackArtists(track);
|
||||||
const description = `${artist} - ${track.album.title}`;
|
const description = `${artist} - ${track.album.title}`;
|
||||||
|
|
@ -136,7 +204,7 @@ export async function onRequest(context) {
|
||||||
console.error('Failed to fetch stream fallback:', e);
|
console.error('Failed to fetch stream fallback:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// this prob wont work im js winging it
|
|
||||||
const audioMeta = audioUrl
|
const audioMeta = audioUrl
|
||||||
? `
|
? `
|
||||||
<meta property="og:audio" content="${audioUrl}">
|
<meta property="og:audio" content="${audioUrl}">
|
||||||
|
|
@ -182,11 +250,11 @@ export async function onRequest(context) {
|
||||||
return new Response(metaHtml, {
|
return new Response(metaHtml, {
|
||||||
headers: { 'content-type': 'text/html;charset=UTF-8' },
|
headers: { 'content-type': 'text/html;charset=UTF-8' },
|
||||||
});
|
});
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error generating meta tags for track ${trackId}:`, error);
|
console.error(`Error generating meta tags for track ${trackId}:`, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const url = new URL(request.url);
|
const url = new URL(request.url);
|
||||||
url.pathname = '/';
|
url.pathname = '/';
|
||||||
|
|
|
||||||
286
package-lock.json
generated
286
package-lock.json
generated
|
|
@ -27,8 +27,8 @@
|
||||||
"butterchurn-presets": "^2.4.7",
|
"butterchurn-presets": "^2.4.7",
|
||||||
"client-zip": "^2.5.0",
|
"client-zip": "^2.5.0",
|
||||||
"cookie-session": "^2.1.1",
|
"cookie-session": "^2.1.1",
|
||||||
"dashjs": "https://github.com/Dash-Industry-Forum/dash.js/archive/refs/tags/v5.1.1.tar.gz",
|
|
||||||
"eventemitter3": "^5.0.4",
|
"eventemitter3": "^5.0.4",
|
||||||
|
"events": "^3.3.0",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"hls.js": "^1.6.15",
|
"hls.js": "^1.6.15",
|
||||||
"jose": "^6.2.0",
|
"jose": "^6.2.0",
|
||||||
|
|
@ -36,6 +36,7 @@
|
||||||
"mime": "^4.1.0",
|
"mime": "^4.1.0",
|
||||||
"npm": "^11.11.1",
|
"npm": "^11.11.1",
|
||||||
"pocketbase": "^0.26.8",
|
"pocketbase": "^0.26.8",
|
||||||
|
"shaka-player": "^5.0.7",
|
||||||
"simple-icons": "^16.12.0",
|
"simple-icons": "^16.12.0",
|
||||||
"svgo": "^4.0.1",
|
"svgo": "^4.0.1",
|
||||||
"url-toolkit": "^2.2.5",
|
"url-toolkit": "^2.2.5",
|
||||||
|
|
@ -4412,110 +4413,6 @@
|
||||||
"string.prototype.matchall": "^4.0.6"
|
"string.prototype.matchall": "^4.0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@svta/cml-608": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-cmcd": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-cta": "1.0.1",
|
|
||||||
"@svta/cml-structured-field-values": "1.0.1",
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-cmsd": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-cta": "1.0.1",
|
|
||||||
"@svta/cml-structured-field-values": "1.0.1",
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-cta": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-structured-field-values": "1.0.1",
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-dash": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-id3": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-request": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-utils": "1.0.1",
|
|
||||||
"@svta/cml-xml": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-structured-field-values": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-utils": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/cml-xml": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
|
||||||
"node": ">=20"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"@svta/cml-utils": "1.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@svta/common-media-library": {
|
"node_modules/@svta/common-media-library": {
|
||||||
"version": "0.18.1",
|
"version": "0.18.1",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
|
|
@ -5264,39 +5161,6 @@
|
||||||
"node": ">=6.0.0"
|
"node": ">=6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/bcp-47": {
|
|
||||||
"version": "2.1.0",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"is-alphabetical": "^2.0.0",
|
|
||||||
"is-alphanumerical": "^2.0.0",
|
|
||||||
"is-decimal": "^2.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/bcp-47-match": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/bcp-47-normalize": {
|
|
||||||
"version": "2.3.0",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"bcp-47": "^2.0.0",
|
|
||||||
"bcp-47-match": "^2.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/big-integer": {
|
"node_modules/big-integer": {
|
||||||
"version": "1.6.52",
|
"version": "1.6.52",
|
||||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
|
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
|
||||||
|
|
@ -5667,10 +5531,6 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/codem-isoboxer": {
|
|
||||||
"version": "0.3.10",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/color": {
|
"node_modules/color": {
|
||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
|
||||||
|
|
@ -6646,30 +6506,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dashjs": {
|
|
||||||
"version": "5.1.1",
|
|
||||||
"resolved": "https://github.com/Dash-Industry-Forum/dash.js/archive/refs/tags/v5.1.1.tar.gz",
|
|
||||||
"integrity": "sha512-lhD1tvEe4PO6t086flm6WfO2Jt1EOIolDQ17F3vLomMthaL1RH96h8peIQTvrDvfSJTRXeisL+CwPj4oud5e9g==",
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"@svta/cml-608": "1.0.1",
|
|
||||||
"@svta/cml-cmcd": "1.0.1",
|
|
||||||
"@svta/cml-cmsd": "1.0.1",
|
|
||||||
"@svta/cml-dash": "1.0.1",
|
|
||||||
"@svta/cml-id3": "1.0.1",
|
|
||||||
"@svta/cml-request": "1.0.1",
|
|
||||||
"@svta/cml-xml": "1.0.1",
|
|
||||||
"bcp-47-match": "^2.0.3",
|
|
||||||
"bcp-47-normalize": "^2.3.0",
|
|
||||||
"codem-isoboxer": "0.3.10",
|
|
||||||
"fast-deep-equal": "3.1.3",
|
|
||||||
"html-entities": "^2.5.2",
|
|
||||||
"imsc": "^1.1.5",
|
|
||||||
"localforage": "^1.10.0",
|
|
||||||
"path-browserify": "^1.0.1",
|
|
||||||
"ua-parser-js": "^1.0.37"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/data-view-buffer": {
|
"node_modules/data-view-buffer": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -7569,6 +7405,15 @@
|
||||||
"version": "5.0.4",
|
"version": "5.0.4",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/events": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/events-universal": {
|
"node_modules/events-universal": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/events-universal/-/events-universal-1.0.1.tgz",
|
||||||
|
|
@ -7599,6 +7444,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/fast-fifo": {
|
"node_modules/fast-fifo": {
|
||||||
|
|
@ -8992,20 +8838,6 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/html-entities": {
|
|
||||||
"version": "2.6.0",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/mdevils"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "patreon",
|
|
||||||
"url": "https://patreon.com/mdevils"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/html-tags": {
|
"node_modules/html-tags": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -9084,10 +8916,6 @@
|
||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/immediate": {
|
|
||||||
"version": "3.0.6",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/import-fresh": {
|
"node_modules/import-fresh": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -9111,17 +8939,6 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/imsc": {
|
|
||||||
"version": "1.1.5",
|
|
||||||
"license": "BSD-2-Clause",
|
|
||||||
"dependencies": {
|
|
||||||
"sax": "1.2.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/imsc/node_modules/sax": {
|
|
||||||
"version": "1.2.1",
|
|
||||||
"license": "ISC"
|
|
||||||
},
|
|
||||||
"node_modules/imurmurhash": {
|
"node_modules/imurmurhash": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -9180,26 +8997,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-alphabetical": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-alphanumerical": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"is-alphabetical": "^2.0.0",
|
|
||||||
"is-decimal": "^2.0.0"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-array-buffer": {
|
"node_modules/is-array-buffer": {
|
||||||
"version": "3.0.5",
|
"version": "3.0.5",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -9324,14 +9121,6 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-decimal": {
|
|
||||||
"version": "2.0.1",
|
|
||||||
"license": "MIT",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/wooorm"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/is-docker": {
|
"node_modules/is-docker": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
|
||||||
|
|
@ -9960,13 +9749,6 @@
|
||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lie": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"immediate": "~3.0.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/lines-and-columns": {
|
"node_modules/lines-and-columns": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -10037,13 +9819,6 @@
|
||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/localforage": {
|
|
||||||
"version": "1.10.0",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"dependencies": {
|
|
||||||
"lie": "3.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/locate-path": {
|
"node_modules/locate-path": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -12635,10 +12410,6 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/path-browserify": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/path-exists": {
|
"node_modules/path-exists": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -14027,6 +13798,15 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/shaka-player": {
|
||||||
|
"version": "5.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/shaka-player/-/shaka-player-5.0.8.tgz",
|
||||||
|
"integrity": "sha512-f886rKRvQ0IKhWGk+rINS++YTjTJyc4DT5YypTsHW6wiNV9fiHi2n35+lg5R+hj9RfhqkmJHMjJb3gprUTNa8w==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sharp": {
|
"node_modules/sharp": {
|
||||||
"version": "0.34.5",
|
"version": "0.34.5",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
@ -15342,30 +15122,6 @@
|
||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ua-parser-js": {
|
|
||||||
"version": "1.0.41",
|
|
||||||
"funding": [
|
|
||||||
{
|
|
||||||
"type": "opencollective",
|
|
||||||
"url": "https://opencollective.com/ua-parser-js"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "paypal",
|
|
||||||
"url": "https://paypal.me/faisalman"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/faisalman"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"bin": {
|
|
||||||
"ua-parser-js": "script/cli.js"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "*"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/uglify-js": {
|
"node_modules/uglify-js": {
|
||||||
"version": "3.19.3",
|
"version": "3.19.3",
|
||||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
|
||||||
|
|
|
||||||
16
styles.css
16
styles.css
|
|
@ -1328,6 +1328,8 @@ ul {
|
||||||
.search-bar {
|
.search-bar {
|
||||||
width: 80%;
|
width: 80%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-bar input {
|
.search-bar input {
|
||||||
|
|
@ -1634,6 +1636,13 @@ input[type='search']::-webkit-search-cancel-button {
|
||||||
gap: var(--spacing-xs);
|
gap: var(--spacing-xs);
|
||||||
margin-bottom: var(--spacing-lg);
|
margin-bottom: var(--spacing-lg);
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-tabs::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-tab {
|
.search-tab {
|
||||||
|
|
@ -1645,6 +1654,8 @@ input[type='search']::-webkit-search-cancel-button {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
/* Keep layout stable */
|
/* Keep layout stable */
|
||||||
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
|
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
|
||||||
|
|
@ -6300,6 +6311,8 @@ img[src=''] {
|
||||||
padding: var(--spacing-md);
|
padding: var(--spacing-md);
|
||||||
grid-area: main;
|
grid-area: main;
|
||||||
overflow-y: visible;
|
overflow-y: visible;
|
||||||
|
overflow-x: hidden;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-header {
|
.main-header {
|
||||||
|
|
@ -6335,6 +6348,7 @@ img[src=''] {
|
||||||
|
|
||||||
.search-bar {
|
.search-bar {
|
||||||
max-width: none;
|
max-width: none;
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.content-section {
|
.content-section {
|
||||||
|
|
@ -6960,6 +6974,8 @@ img[src=''] {
|
||||||
.main-content {
|
.main-content {
|
||||||
padding: var(--spacing-sm);
|
padding: var(--spacing-sm);
|
||||||
grid-area: main;
|
grid-area: main;
|
||||||
|
overflow-x: hidden;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar:not(.waveform-loaded),
|
.progress-bar:not(.waveform-loaded),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue