mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-09 01:31:46 +00:00
feat(synced-lyrics): romanization (#2790)
* feat(synced-lyrics): init romanization! * remove debug logs and add TODO * feat(synced-lyrics/romanization): Mandarin! * feat(synced-lyrics/romanization): improve japanese detection * feat(synced-lyrics/romanization): Korean! * qol(synced-lyrics/romanization): canonicalize punctuation and symbols * feat(synced-lyrics/romanization): handle japanese+korean and korean+chinese lyrics * revert formatting on electron.vite.config.mts * feat(synced-lyrics/romanization): romanize plain lyrics * apply fix by @kimjammer * fix lockfile due to rebase * feat(synced-lyrics): improve lyric processing and formatting; * feat(synced-lyrics/romanization): add option to enable/disable romanization * chore: move default value for --lyrics-duration to the declaration * update lockfile * fix: improvement 1. improved language detection logic 2. changed code to work in the renderer process * fix: fix regression (canonicalize) --------- Co-authored-by: JellyBrick <shlee1503@naver.com>
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import { resolve, dirname, join } from 'node:path';
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
import { UserConfig } from 'vite';
|
||||
|
||||
12
package.json
12
package.json
@ -231,7 +231,8 @@
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"vudio@2.1.1": "patches/vudio@2.1.1.patch",
|
||||
"@malept/flatpak-bundler": "patches/@malept__flatpak-bundler.patch"
|
||||
"@malept/flatpak-bundler@0.4.0": "patches/@malept__flatpak-bundler@0.4.0.patch",
|
||||
"kuromoji@0.1.2": "patches/kuromoji@0.1.2.patch"
|
||||
},
|
||||
"neverBuiltDependencies": []
|
||||
},
|
||||
@ -268,9 +269,11 @@
|
||||
"electron-store": "10.0.1",
|
||||
"electron-unhandled": "4.0.1",
|
||||
"electron-updater": "6.3.9",
|
||||
"es-hangul": "2.2.4",
|
||||
"fast-average-color": "9.5.0",
|
||||
"fast-equals": "5.2.2",
|
||||
"filenamify": "6.0.0",
|
||||
"hanja": "1.1.4",
|
||||
"happy-dom": "17.4.4",
|
||||
"hono": "4.7.5",
|
||||
"howler": "2.2.4",
|
||||
@ -279,9 +282,15 @@
|
||||
"jimp": "1.6.0",
|
||||
"keyboardevent-from-electron-accelerator": "2.0.0",
|
||||
"keyboardevents-areequal": "0.2.2",
|
||||
"kuromoji": "0.1.2",
|
||||
"kuroshiro": "1.2.0",
|
||||
"kuroshiro-analyzer-kuromoji": "1.1.0",
|
||||
"lazy-var": "2.2.2",
|
||||
"node-html-parser": "7.0.1",
|
||||
"node-id3": "0.2.8",
|
||||
"peerjs": "1.5.4",
|
||||
"pinyin": "4.0.0-alpha.2",
|
||||
"segmentit": "2.0.3",
|
||||
"semver": "7.7.1",
|
||||
"serve": "14.2.4",
|
||||
"simple-youtube-age-restriction-bypass": "github:organization/Simple-YouTube-Age-Restriction-Bypass#v2.5.9",
|
||||
@ -297,6 +306,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "9.22.0",
|
||||
"@malept/flatpak-bundler": "0.4.0",
|
||||
"@playwright/test": "1.51.1",
|
||||
"@stylistic/eslint-plugin-js": "4.2.0",
|
||||
"@total-typescript/ts-reset": "0.6.1",
|
||||
|
||||
@ -1,161 +0,0 @@
|
||||
diff --git a/lib/importDeclaration.js b/lib/importDeclaration.js
|
||||
index afb4de779034cfea080825a5f4320661c48bee32..f10b0a11a39577fbd42569e6b0e768255c1ef276 100644
|
||||
--- a/lib/importDeclaration.js
|
||||
+++ b/lib/importDeclaration.js
|
||||
@@ -1,5 +1,5 @@
|
||||
-"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports["default"] = importDeclaration;function importDeclaration(context) {
|
||||
- var ancestors = context.getAncestors();
|
||||
+"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports["default"] = importDeclaration;function importDeclaration(context, node) {
|
||||
+ var ancestors = context.getSourceCode().getAncestors(node);
|
||||
return ancestors[ancestors.length - 1];
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9pbXBvcnREZWNsYXJhdGlvbi5qcyJdLCJuYW1lcyI6WyJpbXBvcnREZWNsYXJhdGlvbiIsImNvbnRleHQiLCJhbmNlc3RvcnMiLCJnZXRBbmNlc3RvcnMiLCJsZW5ndGgiXSwibWFwcGluZ3MiOiJnR0FBd0JBLGlCLENBQVQsU0FBU0EsaUJBQVQsQ0FBMkJDLE9BQTNCLEVBQW9DO0FBQ2pELE1BQU1DLFlBQVlELFFBQVFFLFlBQVIsRUFBbEI7QUFDQSxTQUFPRCxVQUFVQSxVQUFVRSxNQUFWLEdBQW1CLENBQTdCLENBQVA7QUFDRCIsImZpbGUiOiJpbXBvcnREZWNsYXJhdGlvbi5qcyIsInNvdXJjZXNDb250ZW50IjpbImV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGltcG9ydERlY2xhcmF0aW9uKGNvbnRleHQpIHtcbiAgY29uc3QgYW5jZXN0b3JzID0gY29udGV4dC5nZXRBbmNlc3RvcnMoKTtcbiAgcmV0dXJuIGFuY2VzdG9yc1thbmNlc3RvcnMubGVuZ3RoIC0gMV07XG59XG4iXX0=
|
||||
\ No newline at end of file
|
||||
diff --git a/lib/rules/first.js b/lib/rules/first.js
|
||||
index a77168660cf32c8c3e96f3ff4b8240a36d7de3a6..c0e00d75f9989916057fef3999eeee8d21820292 100644
|
||||
--- a/lib/rules/first.js
|
||||
+++ b/lib/rules/first.js
|
||||
@@ -66,7 +66,7 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
if (nonImportCount > 0) {var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
|
||||
- for (var _iterator = context.getDeclaredVariables(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var variable = _step.value;
|
||||
+ for (var _iterator = sourceCode.getDeclaredVariables(node)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var variable = _step.value;
|
||||
if (!shouldSort) {break;}
|
||||
var references = variable.references;
|
||||
if (references.length) {var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
|
||||
diff --git a/lib/rules/namespace.js b/lib/rules/namespace.js
|
||||
index 574d89a60d15c7e0e712956ea6a3ad2d0eac7f08..82e7cb3cff4246592d762cce86323f2b72de92e4 100644
|
||||
--- a/lib/rules/namespace.js
|
||||
+++ b/lib/rules/namespace.js
|
||||
@@ -86,7 +86,7 @@ module.exports = {
|
||||
|
||||
// same as above, but does not add names to local map
|
||||
ExportNamespaceSpecifier: function () {function ExportNamespaceSpecifier(namespace) {
|
||||
- var declaration = (0, _importDeclaration2['default'])(context);
|
||||
+ var declaration = (0, _importDeclaration2['default'])(context, namespace);
|
||||
|
||||
var imports = _ExportMap2['default'].get(declaration.source.value, context);
|
||||
if (imports == null) {return null;}
|
||||
diff --git a/lib/rules/newline-after-import.js b/lib/rules/newline-after-import.js
|
||||
index 6cc15686464a17803a0b976c35b99627cdbfabee..520eec6d9a375527ab72c459960fe4416c046c17 100644
|
||||
--- a/lib/rules/newline-after-import.js
|
||||
+++ b/lib/rules/newline-after-import.js
|
||||
@@ -194,7 +194,7 @@ module.exports = {
|
||||
}return CallExpression;}(),
|
||||
'Program:exit': function () {function ProgramExit() {
|
||||
log('exit processing for', context.getPhysicalFilename ? context.getPhysicalFilename() : context.getFilename());
|
||||
- var scopeBody = getScopeBody(context.getScope());
|
||||
+ var scopeBody = getScopeBody(context.getSourceCode().getScope(node));
|
||||
log('got scope:', scopeBody);
|
||||
|
||||
requireCalls.forEach(function (node, index) {
|
||||
diff --git a/lib/rules/no-amd.js b/lib/rules/no-amd.js
|
||||
index 7ac108bf812ca4f78bfa6fe5ae8b9cf38e2ff497..346c3105dc70f72c4d76fcc6b96b946d1d4ec6d5 100644
|
||||
--- a/lib/rules/no-amd.js
|
||||
+++ b/lib/rules/no-amd.js
|
||||
@@ -23,7 +23,7 @@ module.exports = {
|
||||
create: function () {function create(context) {
|
||||
return {
|
||||
CallExpression: function () {function CallExpression(node) {
|
||||
- if (context.getScope().type !== 'module') {return;}
|
||||
+ if (context.getSourceCode().getScope(node).type !== 'module') {return;}
|
||||
|
||||
if (node.callee.type !== 'Identifier') {return;}
|
||||
if (node.callee.name !== 'require' && node.callee.name !== 'define') {return;}
|
||||
diff --git a/lib/rules/no-commonjs.js b/lib/rules/no-commonjs.js
|
||||
index befeff0026d61d3ac1e6bbcea29f5c471dc1d353..e91c5ed34e968d5867e884ea800e166cda345aef 100644
|
||||
--- a/lib/rules/no-commonjs.js
|
||||
+++ b/lib/rules/no-commonjs.js
|
||||
@@ -107,7 +107,7 @@ module.exports = {
|
||||
|
||||
// exports.
|
||||
if (node.object.name === 'exports') {
|
||||
- var isInScope = context.getScope().
|
||||
+ var isInScope = context.getSourceCode().getScope(node).
|
||||
variables.
|
||||
some(function (variable) {return variable.name === 'exports';});
|
||||
if (!isInScope) {
|
||||
@@ -117,7 +117,7 @@ module.exports = {
|
||||
|
||||
}return MemberExpression;}(),
|
||||
CallExpression: function () {function CallExpression(call) {
|
||||
- if (!validateScope(context.getScope())) {return;}
|
||||
+ if (!validateScope(context.getSourceCode().getScope(call))) {return;}
|
||||
|
||||
if (call.callee.type !== 'Identifier') {return;}
|
||||
if (call.callee.name !== 'require') {return;}
|
||||
diff --git a/lib/rules/no-mutable-exports.js b/lib/rules/no-mutable-exports.js
|
||||
index 40bd1b4cfa95d41732bb13bba0ed1969a91cc7ff..8a25abfbfadb299204b36a6cbf283259bcc2e790 100644
|
||||
--- a/lib/rules/no-mutable-exports.js
|
||||
+++ b/lib/rules/no-mutable-exports.js
|
||||
@@ -32,7 +32,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
function handleExportDefault(node) {
|
||||
- var scope = context.getScope();
|
||||
+ var scope = context.getSourceCode().getScope(node);
|
||||
|
||||
if (node.declaration.name) {
|
||||
checkDeclarationsInScope(scope, node.declaration.name);
|
||||
@@ -40,7 +40,7 @@ module.exports = {
|
||||
}
|
||||
|
||||
function handleExportNamed(node) {
|
||||
- var scope = context.getScope();
|
||||
+ var scope = context.getSourceCode().getScope(node);
|
||||
|
||||
if (node.declaration) {
|
||||
checkDeclaration(node.declaration);
|
||||
diff --git a/lib/rules/no-named-as-default-member.js b/lib/rules/no-named-as-default-member.js
|
||||
index 0c15051e027ad7d1d45f1b51c20be1c000b0af01..5b3d6ba415511b7f9f83a52e1acfebe5a1045a7b 100644
|
||||
--- a/lib/rules/no-named-as-default-member.js
|
||||
+++ b/lib/rules/no-named-as-default-member.js
|
||||
@@ -35,7 +35,7 @@ module.exports = {
|
||||
|
||||
return {
|
||||
ImportDefaultSpecifier: function () {function ImportDefaultSpecifier(node) {
|
||||
- var declaration = (0, _importDeclaration2['default'])(context);
|
||||
+ var declaration = (0, _importDeclaration2['default'])(context, node);
|
||||
var exportMap = _ExportMap2['default'].get(declaration.source.value, context);
|
||||
if (exportMap == null) {return;}
|
||||
|
||||
diff --git a/lib/rules/no-named-as-default.js b/lib/rules/no-named-as-default.js
|
||||
index 63378a33a1c7da004c57a524cec1a1cddf23e210..c81b1f93b11628676158b79f1c4015911943cc7d 100644
|
||||
--- a/lib/rules/no-named-as-default.js
|
||||
+++ b/lib/rules/no-named-as-default.js
|
||||
@@ -18,7 +18,7 @@ module.exports = {
|
||||
// #566: default is a valid specifier
|
||||
if (defaultSpecifier[nameKey].name === 'default') {return;}
|
||||
|
||||
- var declaration = (0, _importDeclaration2['default'])(context);
|
||||
+ var declaration = (0, _importDeclaration2['default'])(context, defaultSpecifier);
|
||||
|
||||
var imports = _ExportMap2['default'].get(declaration.source.value, context);
|
||||
if (imports == null) {return;}
|
||||
diff --git a/lib/rules/no-namespace.js b/lib/rules/no-namespace.js
|
||||
index 2b0c783adea788101b779b17f977bbcb582cfd3f..a7f7b202ac7c4a342febef2a993586c4cc84fc7a 100644
|
||||
--- a/lib/rules/no-namespace.js
|
||||
+++ b/lib/rules/no-namespace.js
|
||||
@@ -43,7 +43,7 @@ var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_doc
|
||||
return;
|
||||
}
|
||||
|
||||
- var scopeVariables = context.getScope().variables;
|
||||
+ var scopeVariables = context.getSourceCode().getScope(node).variables;
|
||||
var namespaceVariable = scopeVariables.find(function (variable) {return variable.defs[0].node === node;});
|
||||
var namespaceReferences = namespaceVariable.references;
|
||||
var namespaceIdentifiers = namespaceReferences.map(function (reference) {return reference.identifier;});
|
||||
diff --git a/package.json b/package.json
|
||||
index 5c0af48543483a21791fa23a4a583071d3551772..5deeac3d0accc3878ef0fc93dfb52a8ca7c46e84 100644
|
||||
--- a/package.json
|
||||
+++ b/package.json
|
||||
@@ -72,7 +72,7 @@
|
||||
"chai": "^4.3.10",
|
||||
"cross-env": "^4.0.0",
|
||||
"escope": "^3.6.0",
|
||||
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8",
|
||||
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9",
|
||||
"eslint-doc-generator": "^1.6.1",
|
||||
"eslint-import-resolver-node": "file:./resolvers/node",
|
||||
"eslint-import-resolver-typescript": "^1.0.2 || ^1.1.1",
|
||||
580
patches/kuromoji@0.1.2.patch
Normal file
580
patches/kuromoji@0.1.2.patch
Normal file
@ -0,0 +1,580 @@
|
||||
diff --git a/build/kuromoji.js b/build/kuromoji.js
|
||||
index f0f4ae9183ff8965fda64a2042f29936f76506d1..8912a754d184742d2768854c7bba83d66f9ff95f 100644
|
||||
--- a/build/kuromoji.js
|
||||
+++ b/build/kuromoji.js
|
||||
@@ -1,5 +1,5 @@
|
||||
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.kuromoji = f()}})(function(){var define,module,exports;return (function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){
|
||||
-(function (process,global){
|
||||
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.kuromoji = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
|
||||
+(function (process,global,setImmediate){(function (){
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||
@@ -666,10 +666,13 @@ var reIsUint = /^(?:0|[1-9]\d*)$/;
|
||||
* @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
|
||||
*/
|
||||
function isIndex(value, length) {
|
||||
+ var type = typeof value;
|
||||
length = length == null ? MAX_SAFE_INTEGER$1 : length;
|
||||
+
|
||||
return !!length &&
|
||||
- (typeof value == 'number' || reIsUint.test(value)) &&
|
||||
- (value > -1 && value % 1 == 0 && value < length);
|
||||
+ (type == 'number' ||
|
||||
+ (type != 'symbol' && reIsUint.test(value))) &&
|
||||
+ (value > -1 && value % 1 == 0 && value < length);
|
||||
}
|
||||
|
||||
/** `Object#toString` result references. */
|
||||
@@ -755,6 +758,14 @@ var freeProcess = moduleExports$1 && freeGlobal.process;
|
||||
/** Used to access faster Node.js helpers. */
|
||||
var nodeUtil = (function() {
|
||||
try {
|
||||
+ // Use `util.types` for Node.js 10+.
|
||||
+ var types = freeModule$1 && freeModule$1.require && freeModule$1.require('util').types;
|
||||
+
|
||||
+ if (types) {
|
||||
+ return types;
|
||||
+ }
|
||||
+
|
||||
+ // Legacy `process.binding('util')` for Node.js < 10.
|
||||
return freeProcess && freeProcess.binding && freeProcess.binding('util');
|
||||
} catch (e) {}
|
||||
}());
|
||||
@@ -939,6 +950,9 @@ function createObjectIterator(obj) {
|
||||
var len = okeys.length;
|
||||
return function next() {
|
||||
var key = okeys[++i];
|
||||
+ if (key === '__proto__') {
|
||||
+ return next();
|
||||
+ }
|
||||
return i < len ? {value: obj[key], key: key} : null;
|
||||
};
|
||||
}
|
||||
@@ -970,6 +984,7 @@ function _eachOfLimit(limit) {
|
||||
var nextElem = iterator(obj);
|
||||
var done = false;
|
||||
var running = 0;
|
||||
+ var looping = false;
|
||||
|
||||
function iterateeCallback(err, value) {
|
||||
running -= 1;
|
||||
@@ -981,12 +996,13 @@ function _eachOfLimit(limit) {
|
||||
done = true;
|
||||
return callback(null);
|
||||
}
|
||||
- else {
|
||||
+ else if (!looping) {
|
||||
replenish();
|
||||
}
|
||||
}
|
||||
|
||||
function replenish () {
|
||||
+ looping = true;
|
||||
while (running < limit && !done) {
|
||||
var elem = nextElem();
|
||||
if (elem === null) {
|
||||
@@ -999,6 +1015,7 @@ function _eachOfLimit(limit) {
|
||||
running += 1;
|
||||
iteratee(elem.value, elem.key, onlyOnce(iterateeCallback));
|
||||
}
|
||||
+ looping = false;
|
||||
}
|
||||
|
||||
replenish();
|
||||
@@ -3819,7 +3836,7 @@ function memoize(fn, hasher) {
|
||||
|
||||
/**
|
||||
* Calls `callback` on a later loop around the event loop. In Node.js this just
|
||||
- * calls `process.nextTicl`. In the browser it will use `setImmediate` if
|
||||
+ * calls `process.nextTick`. In the browser it will use `setImmediate` if
|
||||
* available, otherwise `setTimeout(callback, 0)`, which means other higher
|
||||
* priority events may precede the execution of `callback`.
|
||||
*
|
||||
@@ -5596,8 +5613,8 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
})));
|
||||
|
||||
-}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||||
-},{"_process":4}],2:[function(require,module,exports){
|
||||
+}).call(this)}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate)
|
||||
+},{"_process":3,"timers":4}],2:[function(require,module,exports){
|
||||
// Copyright (c) 2014 Takuya Asano All Rights Reserved.
|
||||
|
||||
(function () {
|
||||
@@ -6391,234 +6408,6 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
||||
})();
|
||||
|
||||
},{}],3:[function(require,module,exports){
|
||||
-(function (process){
|
||||
-// Copyright Joyent, Inc. and other Node contributors.
|
||||
-//
|
||||
-// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
-// copy of this software and associated documentation files (the
|
||||
-// "Software"), to deal in the Software without restriction, including
|
||||
-// without limitation the rights to use, copy, modify, merge, publish,
|
||||
-// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
-// persons to whom the Software is furnished to do so, subject to the
|
||||
-// following conditions:
|
||||
-//
|
||||
-// The above copyright notice and this permission notice shall be included
|
||||
-// in all copies or substantial portions of the Software.
|
||||
-//
|
||||
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
-
|
||||
-// resolves . and .. elements in a path array with directory names there
|
||||
-// must be no slashes, empty elements, or device names (c:\) in the array
|
||||
-// (so also no leading and trailing slashes - it does not distinguish
|
||||
-// relative and absolute paths)
|
||||
-function normalizeArray(parts, allowAboveRoot) {
|
||||
- // if the path tries to go above the root, `up` ends up > 0
|
||||
- var up = 0;
|
||||
- for (var i = parts.length - 1; i >= 0; i--) {
|
||||
- var last = parts[i];
|
||||
- if (last === '.') {
|
||||
- parts.splice(i, 1);
|
||||
- } else if (last === '..') {
|
||||
- parts.splice(i, 1);
|
||||
- up++;
|
||||
- } else if (up) {
|
||||
- parts.splice(i, 1);
|
||||
- up--;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // if the path is allowed to go above the root, restore leading ..s
|
||||
- if (allowAboveRoot) {
|
||||
- for (; up--; up) {
|
||||
- parts.unshift('..');
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return parts;
|
||||
-}
|
||||
-
|
||||
-// Split a filename into [root, dir, basename, ext], unix version
|
||||
-// 'root' is just a slash, or nothing.
|
||||
-var splitPathRe =
|
||||
- /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
|
||||
-var splitPath = function(filename) {
|
||||
- return splitPathRe.exec(filename).slice(1);
|
||||
-};
|
||||
-
|
||||
-// path.resolve([from ...], to)
|
||||
-// posix version
|
||||
-exports.resolve = function() {
|
||||
- var resolvedPath = '',
|
||||
- resolvedAbsolute = false;
|
||||
-
|
||||
- for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
||||
- var path = (i >= 0) ? arguments[i] : process.cwd();
|
||||
-
|
||||
- // Skip empty and invalid entries
|
||||
- if (typeof path !== 'string') {
|
||||
- throw new TypeError('Arguments to path.resolve must be strings');
|
||||
- } else if (!path) {
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- resolvedPath = path + '/' + resolvedPath;
|
||||
- resolvedAbsolute = path.charAt(0) === '/';
|
||||
- }
|
||||
-
|
||||
- // At this point the path should be resolved to a full absolute path, but
|
||||
- // handle relative paths to be safe (might happen when process.cwd() fails)
|
||||
-
|
||||
- // Normalize the path
|
||||
- resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
|
||||
- return !!p;
|
||||
- }), !resolvedAbsolute).join('/');
|
||||
-
|
||||
- return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
|
||||
-};
|
||||
-
|
||||
-// path.normalize(path)
|
||||
-// posix version
|
||||
-exports.normalize = function(path) {
|
||||
- var isAbsolute = exports.isAbsolute(path),
|
||||
- trailingSlash = substr(path, -1) === '/';
|
||||
-
|
||||
- // Normalize the path
|
||||
- path = normalizeArray(filter(path.split('/'), function(p) {
|
||||
- return !!p;
|
||||
- }), !isAbsolute).join('/');
|
||||
-
|
||||
- if (!path && !isAbsolute) {
|
||||
- path = '.';
|
||||
- }
|
||||
- if (path && trailingSlash) {
|
||||
- path += '/';
|
||||
- }
|
||||
-
|
||||
- return (isAbsolute ? '/' : '') + path;
|
||||
-};
|
||||
-
|
||||
-// posix version
|
||||
-exports.isAbsolute = function(path) {
|
||||
- return path.charAt(0) === '/';
|
||||
-};
|
||||
-
|
||||
-// posix version
|
||||
-exports.join = function() {
|
||||
- var paths = Array.prototype.slice.call(arguments, 0);
|
||||
- return exports.normalize(filter(paths, function(p, index) {
|
||||
- if (typeof p !== 'string') {
|
||||
- throw new TypeError('Arguments to path.join must be strings');
|
||||
- }
|
||||
- return p;
|
||||
- }).join('/'));
|
||||
-};
|
||||
-
|
||||
-
|
||||
-// path.relative(from, to)
|
||||
-// posix version
|
||||
-exports.relative = function(from, to) {
|
||||
- from = exports.resolve(from).substr(1);
|
||||
- to = exports.resolve(to).substr(1);
|
||||
-
|
||||
- function trim(arr) {
|
||||
- var start = 0;
|
||||
- for (; start < arr.length; start++) {
|
||||
- if (arr[start] !== '') break;
|
||||
- }
|
||||
-
|
||||
- var end = arr.length - 1;
|
||||
- for (; end >= 0; end--) {
|
||||
- if (arr[end] !== '') break;
|
||||
- }
|
||||
-
|
||||
- if (start > end) return [];
|
||||
- return arr.slice(start, end - start + 1);
|
||||
- }
|
||||
-
|
||||
- var fromParts = trim(from.split('/'));
|
||||
- var toParts = trim(to.split('/'));
|
||||
-
|
||||
- var length = Math.min(fromParts.length, toParts.length);
|
||||
- var samePartsLength = length;
|
||||
- for (var i = 0; i < length; i++) {
|
||||
- if (fromParts[i] !== toParts[i]) {
|
||||
- samePartsLength = i;
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- var outputParts = [];
|
||||
- for (var i = samePartsLength; i < fromParts.length; i++) {
|
||||
- outputParts.push('..');
|
||||
- }
|
||||
-
|
||||
- outputParts = outputParts.concat(toParts.slice(samePartsLength));
|
||||
-
|
||||
- return outputParts.join('/');
|
||||
-};
|
||||
-
|
||||
-exports.sep = '/';
|
||||
-exports.delimiter = ':';
|
||||
-
|
||||
-exports.dirname = function(path) {
|
||||
- var result = splitPath(path),
|
||||
- root = result[0],
|
||||
- dir = result[1];
|
||||
-
|
||||
- if (!root && !dir) {
|
||||
- // No dirname whatsoever
|
||||
- return '.';
|
||||
- }
|
||||
-
|
||||
- if (dir) {
|
||||
- // It has a dirname, strip trailing slash
|
||||
- dir = dir.substr(0, dir.length - 1);
|
||||
- }
|
||||
-
|
||||
- return root + dir;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-exports.basename = function(path, ext) {
|
||||
- var f = splitPath(path)[2];
|
||||
- // TODO: make this comparison case-insensitive on windows?
|
||||
- if (ext && f.substr(-1 * ext.length) === ext) {
|
||||
- f = f.substr(0, f.length - ext.length);
|
||||
- }
|
||||
- return f;
|
||||
-};
|
||||
-
|
||||
-
|
||||
-exports.extname = function(path) {
|
||||
- return splitPath(path)[3];
|
||||
-};
|
||||
-
|
||||
-function filter (xs, f) {
|
||||
- if (xs.filter) return xs.filter(f);
|
||||
- var res = [];
|
||||
- for (var i = 0; i < xs.length; i++) {
|
||||
- if (f(xs[i], i, xs)) res.push(xs[i]);
|
||||
- }
|
||||
- return res;
|
||||
-}
|
||||
-
|
||||
-// String.prototype.substr - negative index don't work in IE8
|
||||
-var substr = 'ab'.substr(-1) === 'b'
|
||||
- ? function (str, start, len) { return str.substr(start, len) }
|
||||
- : function (str, start, len) {
|
||||
- if (start < 0) start = str.length + start;
|
||||
- return str.substr(start, len);
|
||||
- }
|
||||
-;
|
||||
-
|
||||
-}).call(this,require('_process'))
|
||||
-},{"_process":4}],4:[function(require,module,exports){
|
||||
// shim for using process in browser
|
||||
var process = module.exports = {};
|
||||
|
||||
@@ -6804,7 +6593,86 @@ process.chdir = function (dir) {
|
||||
};
|
||||
process.umask = function() { return 0; };
|
||||
|
||||
-},{}],5:[function(require,module,exports){
|
||||
+},{}],4:[function(require,module,exports){
|
||||
+(function (setImmediate,clearImmediate){(function (){
|
||||
+var nextTick = require('process/browser.js').nextTick;
|
||||
+var apply = Function.prototype.apply;
|
||||
+var slice = Array.prototype.slice;
|
||||
+var immediateIds = {};
|
||||
+var nextImmediateId = 0;
|
||||
+
|
||||
+// DOM APIs, for completeness
|
||||
+
|
||||
+exports.setTimeout = function() {
|
||||
+ return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
|
||||
+};
|
||||
+exports.setInterval = function() {
|
||||
+ return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
|
||||
+};
|
||||
+exports.clearTimeout =
|
||||
+exports.clearInterval = function(timeout) { timeout.close(); };
|
||||
+
|
||||
+function Timeout(id, clearFn) {
|
||||
+ this._id = id;
|
||||
+ this._clearFn = clearFn;
|
||||
+}
|
||||
+Timeout.prototype.unref = Timeout.prototype.ref = function() {};
|
||||
+Timeout.prototype.close = function() {
|
||||
+ this._clearFn.call(window, this._id);
|
||||
+};
|
||||
+
|
||||
+// Does not start the time, just sets up the members needed.
|
||||
+exports.enroll = function(item, msecs) {
|
||||
+ clearTimeout(item._idleTimeoutId);
|
||||
+ item._idleTimeout = msecs;
|
||||
+};
|
||||
+
|
||||
+exports.unenroll = function(item) {
|
||||
+ clearTimeout(item._idleTimeoutId);
|
||||
+ item._idleTimeout = -1;
|
||||
+};
|
||||
+
|
||||
+exports._unrefActive = exports.active = function(item) {
|
||||
+ clearTimeout(item._idleTimeoutId);
|
||||
+
|
||||
+ var msecs = item._idleTimeout;
|
||||
+ if (msecs >= 0) {
|
||||
+ item._idleTimeoutId = setTimeout(function onTimeout() {
|
||||
+ if (item._onTimeout)
|
||||
+ item._onTimeout();
|
||||
+ }, msecs);
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+// That's not how node.js implements it but the exposed api is the same.
|
||||
+exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) {
|
||||
+ var id = nextImmediateId++;
|
||||
+ var args = arguments.length < 2 ? false : slice.call(arguments, 1);
|
||||
+
|
||||
+ immediateIds[id] = true;
|
||||
+
|
||||
+ nextTick(function onNextTick() {
|
||||
+ if (immediateIds[id]) {
|
||||
+ // fn.call() is faster so we optimize for the common use-case
|
||||
+ // @see http://jsperf.com/call-apply-segu
|
||||
+ if (args) {
|
||||
+ fn.apply(null, args);
|
||||
+ } else {
|
||||
+ fn.call(null);
|
||||
+ }
|
||||
+ // Prevent ids from leaking
|
||||
+ exports.clearImmediate(id);
|
||||
+ }
|
||||
+ });
|
||||
+
|
||||
+ return id;
|
||||
+};
|
||||
+
|
||||
+exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) {
|
||||
+ delete immediateIds[id];
|
||||
+};
|
||||
+}).call(this)}).call(this,require("timers").setImmediate,require("timers").clearImmediate)
|
||||
+},{"process/browser.js":3,"timers":4}],5:[function(require,module,exports){
|
||||
/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function n(e){throw e;}var p=void 0,aa=this;function t(e,b){var d=e.split("."),c=aa;!(d[0]in c)&&c.execScript&&c.execScript("var "+d[0]);for(var a;d.length&&(a=d.shift());)!d.length&&b!==p?c[a]=b:c=c[a]?c[a]:c[a]={}};var x="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;new (x?Uint8Array:Array)(256);var y;for(y=0;256>y;++y)for(var A=y,ba=7,A=A>>>1;A;A>>>=1)--ba;function B(e,b,d){var c,a="number"===typeof b?b:b=0,f="number"===typeof d?d:e.length;c=-1;for(a=f&7;a--;++b)c=c>>>8^C[(c^e[b])&255];for(a=f>>3;a--;b+=8)c=c>>>8^C[(c^e[b])&255],c=c>>>8^C[(c^e[b+1])&255],c=c>>>8^C[(c^e[b+2])&255],c=c>>>8^C[(c^e[b+3])&255],c=c>>>8^C[(c^e[b+4])&255],c=c>>>8^C[(c^e[b+5])&255],c=c>>>8^C[(c^e[b+6])&255],c=c>>>8^C[(c^e[b+7])&255];return(c^4294967295)>>>0}
|
||||
var D=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
|
||||
2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
|
||||
@@ -6984,7 +6852,7 @@ module.exports = Tokenizer;
|
||||
"use strict";
|
||||
|
||||
var Tokenizer = require("./Tokenizer");
|
||||
-var DictionaryLoader = require("./loader/NodeDictionaryLoader");
|
||||
+var BrowserDictionaryLoader = require("./loader/BrowserDictionaryLoader");
|
||||
|
||||
/**
|
||||
* TokenizerBuilder create Tokenizer instance.
|
||||
@@ -7005,7 +6873,7 @@ function TokenizerBuilder(option) {
|
||||
* @param {TokenizerBuilder~onLoad} callback Callback function
|
||||
*/
|
||||
TokenizerBuilder.prototype.build = function (callback) {
|
||||
- var loader = new DictionaryLoader(this.dic_path);
|
||||
+ var loader = new BrowserDictionaryLoader(this.dic_path);
|
||||
loader.load(function (err, dic) {
|
||||
callback(err, new Tokenizer(dic));
|
||||
});
|
||||
@@ -7020,7 +6888,7 @@ TokenizerBuilder.prototype.build = function (callback) {
|
||||
|
||||
module.exports = TokenizerBuilder;
|
||||
|
||||
-},{"./Tokenizer":6,"./loader/NodeDictionaryLoader":19}],8:[function(require,module,exports){
|
||||
+},{"./Tokenizer":6,"./loader/BrowserDictionaryLoader":19}],8:[function(require,module,exports){
|
||||
/*
|
||||
* Copyright 2014 Takuya Asano
|
||||
* Copyright 2010-2014 Atilika Inc. and contributors
|
||||
@@ -8163,7 +8031,6 @@ module.exports = BrowserDictionaryLoader;
|
||||
|
||||
"use strict";
|
||||
|
||||
-var path = require("path");
|
||||
var async = require("async");
|
||||
var DynamicDictionaries = require("../dict/DynamicDictionaries");
|
||||
|
||||
@@ -8194,7 +8061,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
// Trie
|
||||
function (callback) {
|
||||
async.map([ "base.dat.gz", "check.dat.gz" ], function (filename, _callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, filename), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + filename, function (err, buffer) {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
@@ -8214,7 +8081,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
// Token info dictionaries
|
||||
function (callback) {
|
||||
async.map([ "tid.dat.gz", "tid_pos.dat.gz", "tid_map.dat.gz" ], function (filename, _callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, filename), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + filename, function (err, buffer) {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
@@ -8234,7 +8101,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
},
|
||||
// Connection cost matrix
|
||||
function (callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, "cc.dat.gz"), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + "cc.dat.gz", function (err, buffer) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
@@ -8246,7 +8113,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
// Unknown dictionaries
|
||||
function (callback) {
|
||||
async.map([ "unk.dat.gz", "unk_pos.dat.gz", "unk_map.dat.gz", "unk_char.dat.gz", "unk_compat.dat.gz", "unk_invoke.dat.gz" ], function (filename, _callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, filename), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + filename, function (err, buffer) {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
@@ -8282,7 +8149,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
|
||||
module.exports = DictionaryLoader;
|
||||
|
||||
-},{"../dict/DynamicDictionaries":11,"async":1,"path":3}],21:[function(require,module,exports){
|
||||
+},{"../dict/DynamicDictionaries":11,"async":1}],21:[function(require,module,exports){
|
||||
/*
|
||||
* Copyright 2014 Takuya Asano
|
||||
* Copyright 2010-2014 Atilika Inc. and contributors
|
||||
diff --git a/src/TokenizerBuilder.js b/src/TokenizerBuilder.js
|
||||
index 9ef5c6a2efc63e8b12735a8a9f1cb08d6c52c20c..98881e9fd731047c3fca848a71ede7e381e74f51 100644
|
||||
--- a/src/TokenizerBuilder.js
|
||||
+++ b/src/TokenizerBuilder.js
|
||||
@@ -18,7 +18,7 @@
|
||||
"use strict";
|
||||
|
||||
var Tokenizer = require("./Tokenizer");
|
||||
-var DictionaryLoader = require("./loader/NodeDictionaryLoader");
|
||||
+var BrowserDictionaryLoader = require("./loader/BrowserDictionaryLoader");
|
||||
|
||||
/**
|
||||
* TokenizerBuilder create Tokenizer instance.
|
||||
@@ -39,7 +39,7 @@ function TokenizerBuilder(option) {
|
||||
* @param {TokenizerBuilder~onLoad} callback Callback function
|
||||
*/
|
||||
TokenizerBuilder.prototype.build = function (callback) {
|
||||
- var loader = new DictionaryLoader(this.dic_path);
|
||||
+ var loader = new BrowserDictionaryLoader(this.dic_path);
|
||||
loader.load(function (err, dic) {
|
||||
callback(err, new Tokenizer(dic));
|
||||
});
|
||||
diff --git a/src/loader/DictionaryLoader.js b/src/loader/DictionaryLoader.js
|
||||
index 5f88c0b7f9a786dd8c072a7b84ae86a6f31412cb..3d6f8a67e16d251b3e4ba4dbbbc947679c364382 100644
|
||||
--- a/src/loader/DictionaryLoader.js
|
||||
+++ b/src/loader/DictionaryLoader.js
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
-var path = require("path");
|
||||
var async = require("async");
|
||||
var DynamicDictionaries = require("../dict/DynamicDictionaries");
|
||||
|
||||
@@ -48,7 +47,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
// Trie
|
||||
function (callback) {
|
||||
async.map([ "base.dat.gz", "check.dat.gz" ], function (filename, _callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, filename), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + filename, function (err, buffer) {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
@@ -68,7 +67,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
// Token info dictionaries
|
||||
function (callback) {
|
||||
async.map([ "tid.dat.gz", "tid_pos.dat.gz", "tid_map.dat.gz" ], function (filename, _callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, filename), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + filename, function (err, buffer) {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
@@ -88,7 +87,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
},
|
||||
// Connection cost matrix
|
||||
function (callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, "cc.dat.gz"), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + "cc.dat.gz", function (err, buffer) {
|
||||
if(err) {
|
||||
return callback(err);
|
||||
}
|
||||
@@ -100,7 +99,7 @@ DictionaryLoader.prototype.load = function (load_callback) {
|
||||
// Unknown dictionaries
|
||||
function (callback) {
|
||||
async.map([ "unk.dat.gz", "unk_pos.dat.gz", "unk_map.dat.gz", "unk_char.dat.gz", "unk_compat.dat.gz", "unk_invoke.dat.gz" ], function (filename, _callback) {
|
||||
- loadArrayBuffer(path.join(dic_path, filename), function (err, buffer) {
|
||||
+ loadArrayBuffer(dic_path + filename, function (err, buffer) {
|
||||
if(err) {
|
||||
return _callback(err);
|
||||
}
|
||||
diff --git a/src/loader/NodeDictionaryLoader.js b/src/loader/NodeDictionaryLoader.js
|
||||
deleted file mode 100644
|
||||
index 26eb79249121efe39bd5ae77c17e1caa197fb4ce..0000000000000000000000000000000000000000
|
||||
220
pnpm-lock.yaml
generated
220
pnpm-lock.yaml
generated
@ -13,9 +13,12 @@ overrides:
|
||||
'@babel/runtime': 7.26.10
|
||||
|
||||
patchedDependencies:
|
||||
'@malept/flatpak-bundler':
|
||||
'@malept/flatpak-bundler@0.4.0':
|
||||
hash: c787371eeb2af011ea934e8818a0dad6d7dcb2df31bbb1686babc7231af0183c
|
||||
path: patches/@malept__flatpak-bundler.patch
|
||||
path: patches/@malept__flatpak-bundler@0.4.0.patch
|
||||
kuromoji@0.1.2:
|
||||
hash: e4a08f477026373a427a51d9bedd268ee22a173850ede3750de32af5d241c28c
|
||||
path: patches/kuromoji@0.1.2.patch
|
||||
vudio@2.1.1:
|
||||
hash: 0e06c2ed11c02bdc490c209fa80070e98517c2735c641f5738b6e15d7dc1959d
|
||||
path: patches/vudio@2.1.1.patch
|
||||
@ -120,6 +123,9 @@ importers:
|
||||
electron-updater:
|
||||
specifier: 6.3.9
|
||||
version: 6.3.9
|
||||
es-hangul:
|
||||
specifier: 2.2.4
|
||||
version: 2.2.4
|
||||
fast-average-color:
|
||||
specifier: 9.5.0
|
||||
version: 9.5.0
|
||||
@ -129,6 +135,9 @@ importers:
|
||||
filenamify:
|
||||
specifier: 6.0.0
|
||||
version: 6.0.0
|
||||
hanja:
|
||||
specifier: 1.1.4
|
||||
version: 1.1.4
|
||||
happy-dom:
|
||||
specifier: 17.4.4
|
||||
version: 17.4.4
|
||||
@ -153,6 +162,18 @@ importers:
|
||||
keyboardevents-areequal:
|
||||
specifier: 0.2.2
|
||||
version: 0.2.2
|
||||
kuromoji:
|
||||
specifier: 0.1.2
|
||||
version: 0.1.2(patch_hash=e4a08f477026373a427a51d9bedd268ee22a173850ede3750de32af5d241c28c)
|
||||
kuroshiro:
|
||||
specifier: 1.2.0
|
||||
version: 1.2.0
|
||||
kuroshiro-analyzer-kuromoji:
|
||||
specifier: 1.1.0
|
||||
version: 1.1.0
|
||||
lazy-var:
|
||||
specifier: 2.2.2
|
||||
version: 2.2.2
|
||||
node-html-parser:
|
||||
specifier: 7.0.1
|
||||
version: 7.0.1
|
||||
@ -162,6 +183,12 @@ importers:
|
||||
peerjs:
|
||||
specifier: 1.5.4
|
||||
version: 1.5.4
|
||||
pinyin:
|
||||
specifier: 4.0.0-alpha.2
|
||||
version: 4.0.0-alpha.2(segmentit@2.0.3)
|
||||
segmentit:
|
||||
specifier: 2.0.3
|
||||
version: 2.0.3
|
||||
semver:
|
||||
specifier: 7.7.1
|
||||
version: 7.7.1
|
||||
@ -202,6 +229,9 @@ importers:
|
||||
'@eslint/js':
|
||||
specifier: 9.22.0
|
||||
version: 9.22.0
|
||||
'@malept/flatpak-bundler':
|
||||
specifier: 0.4.0
|
||||
version: 0.4.0(patch_hash=c787371eeb2af011ea934e8818a0dad6d7dcb2df31bbb1686babc7231af0183c)
|
||||
'@playwright/test':
|
||||
specifier: 1.51.1
|
||||
version: 1.51.1
|
||||
@ -1383,6 +1413,9 @@ packages:
|
||||
'@types/node@22.13.5':
|
||||
resolution: {integrity: sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg==}
|
||||
|
||||
'@types/parse-json@4.0.2':
|
||||
resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
|
||||
|
||||
'@types/plist@3.0.5':
|
||||
resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
|
||||
|
||||
@ -1669,6 +1702,9 @@ packages:
|
||||
async-mutex@0.5.0:
|
||||
resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==}
|
||||
|
||||
async@2.6.4:
|
||||
resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==}
|
||||
|
||||
async@3.2.6:
|
||||
resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
|
||||
|
||||
@ -1695,6 +1731,13 @@ packages:
|
||||
peerDependencies:
|
||||
'@babel/core': ^7.20.12
|
||||
|
||||
babel-plugin-macros@2.8.0:
|
||||
resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==}
|
||||
|
||||
babel-plugin-preval@4.0.0:
|
||||
resolution: {integrity: sha512-fZI/4cYneinlj2k/FsXw0/lTWSC5KKoepUueS1g25Gb5vx3GrRyaVwxWCshYqx11GEU4mZnbbFhee8vpquFS2w==}
|
||||
engines: {node: '>=8', npm: '>=6'}
|
||||
|
||||
babel-preset-solid@1.9.5:
|
||||
resolution: {integrity: sha512-85I3osODJ1LvZbv8wFozROV1vXq32BubqHXAGu73A//TRs3NLI1OFP83AQBUTSQHwgZQmARjHlJciym3we+V+w==}
|
||||
peerDependencies:
|
||||
@ -1927,6 +1970,10 @@ packages:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
|
||||
commander@1.1.1:
|
||||
resolution: {integrity: sha512-71Rod2AhcH3JhkBikVpNd0pA+fWsmAaVoti6OR38T76chA7vE3pSerS0Jor4wDw+tOueD2zLVvFOw5H0Rcj7rA==}
|
||||
engines: {node: '>= 0.6.x'}
|
||||
|
||||
commander@5.1.0:
|
||||
resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
|
||||
engines: {node: '>= 6'}
|
||||
@ -1970,6 +2017,10 @@ packages:
|
||||
core-util-is@1.0.3:
|
||||
resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
|
||||
|
||||
cosmiconfig@6.0.0:
|
||||
resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
crc@3.8.0:
|
||||
resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==}
|
||||
|
||||
@ -2159,6 +2210,9 @@ packages:
|
||||
resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
doublearray@0.0.2:
|
||||
resolution: {integrity: sha512-aw55FtZzT6AmiamEj2kvmR6BuFqvYgKZUkfQ7teqVRNqD5UE0rw8IeW/3gieHNKQ5sPuDKlljWEn4bzv5+1bHw==}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2281,6 +2335,9 @@ packages:
|
||||
err-code@2.0.3:
|
||||
resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
|
||||
|
||||
error-ex@1.3.2:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
|
||||
error-stack-parser-es@1.0.5:
|
||||
resolution: {integrity: sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==}
|
||||
|
||||
@ -2299,6 +2356,9 @@ packages:
|
||||
es-get-iterator@1.1.3:
|
||||
resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==}
|
||||
|
||||
es-hangul@2.2.4:
|
||||
resolution: {integrity: sha512-P0zZh+dADhefLo/KEYzTs2d29H+w99c9X6aUeVIoMxTBE1Z8H4/a4e4ZN3u8rmRD+3uOEhNfWXH/NX5dF4aixw==}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -2738,6 +2798,9 @@ packages:
|
||||
graphemer@1.4.0:
|
||||
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
|
||||
|
||||
hanja@1.1.4:
|
||||
resolution: {integrity: sha512-O8K0+9jyibUlmLd/WAXCQ+8XGersUm9PloQuEXFPRfiUztFHRz4WaELXij0iejtl8AN85FxWQYSNmAuoXLircA==}
|
||||
|
||||
happy-dom@17.4.4:
|
||||
resolution: {integrity: sha512-/Pb0ctk3HTZ5xEL3BZ0hK1AqDSAUuRQitOmROPHhfUYEWpmTImwfD8vFDGADmMAX0JYgbcgxWoLFKtsWhcpuVA==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
@ -2903,6 +2966,9 @@ packages:
|
||||
resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
|
||||
is-async-function@2.1.1:
|
||||
resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@ -3127,6 +3193,9 @@ packages:
|
||||
json-buffer@3.0.1:
|
||||
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
|
||||
|
||||
json-parse-even-better-errors@2.3.1:
|
||||
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
|
||||
|
||||
json-schema-traverse@0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
|
||||
@ -3166,12 +3235,28 @@ packages:
|
||||
keyboardevents-areequal@0.2.2:
|
||||
resolution: {integrity: sha512-Nv+Kr33T0mEjxR500q+I6IWisOQ0lK1GGOncV0kWE6n4KFmpcu7RUX5/2B0EUtX51Cb0HjZ9VJsSY3u4cBa0kw==}
|
||||
|
||||
keypress@0.1.0:
|
||||
resolution: {integrity: sha512-x0yf9PL/nx9Nw9oLL8ZVErFAk85/lslwEP7Vz7s5SI1ODXZIgit3C5qyWjw4DxOuO/3Hb4866SQh28a1V1d+WA==}
|
||||
|
||||
keyv@4.5.4:
|
||||
resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
|
||||
|
||||
kuromoji@0.1.2:
|
||||
resolution: {integrity: sha512-V0dUf+C2LpcPEXhoHLMAop/bOht16Dyr+mDiIE39yX3vqau7p80De/koFqpiTcL1zzdZlc3xuHZ8u5gjYRfFaQ==}
|
||||
|
||||
kuroshiro-analyzer-kuromoji@1.1.0:
|
||||
resolution: {integrity: sha512-BSJFhpsQdPwfFLfjKxfLA9iL+/PC6LCR9vgwgb5Jc7jZwk9ilX8SAV6CwhAQZY611tiuhbB52ONYKDO8hgY1bA==}
|
||||
|
||||
kuroshiro@1.2.0:
|
||||
resolution: {integrity: sha512-yBGCK9oDOY3LGZ/KXaN9m7ADcAuSczOR2FoMRYwHLUlis3/o/uxdMVROAjENFO0NQJgALhIdWxI/vIBVrMCk9w==}
|
||||
engines: {node: '>=6.5.0'}
|
||||
|
||||
lazy-val@1.0.5:
|
||||
resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==}
|
||||
|
||||
lazy-var@2.2.2:
|
||||
resolution: {integrity: sha512-158qpmga63PQS6ZmnmrASQ/I+L7ACqczyR6vt61UHBlcVVMddPQIKgG8i63QRgLh98FLawo8qXkJS0gAJi39gQ==}
|
||||
|
||||
leac@0.6.0:
|
||||
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
|
||||
|
||||
@ -3185,6 +3270,9 @@ packages:
|
||||
lie@3.3.0:
|
||||
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
|
||||
|
||||
lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
|
||||
locate-path@6.0.0:
|
||||
resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
|
||||
engines: {node: '>=10'}
|
||||
@ -3598,6 +3686,10 @@ packages:
|
||||
parse-bmfont-xml@1.1.6:
|
||||
resolution: {integrity: sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==}
|
||||
|
||||
parse-json@5.2.0:
|
||||
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
parse5@7.2.1:
|
||||
resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==}
|
||||
|
||||
@ -3636,6 +3728,10 @@ packages:
|
||||
path-to-regexp@3.3.0:
|
||||
resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==}
|
||||
|
||||
path-type@4.0.0:
|
||||
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
path-type@6.0.0:
|
||||
resolution: {integrity: sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==}
|
||||
engines: {node: '>=18'}
|
||||
@ -3682,6 +3778,22 @@ packages:
|
||||
resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
pinyin@4.0.0-alpha.2:
|
||||
resolution: {integrity: sha512-SED2wWr1X0QwH6rXIDgg20zS1mAk0AVMO8eM3KomUlOYzC8mNMWZnspZWhhI0M8MBIbF2xwa+5r30jTSjAqNsg==}
|
||||
engines: {install-node: ^18.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@node-rs/jieba': ^1.6.0
|
||||
nodejieba: 2.5.2
|
||||
segmentit: ^2.0.3
|
||||
peerDependenciesMeta:
|
||||
'@node-rs/jieba':
|
||||
optional: true
|
||||
nodejieba:
|
||||
optional: true
|
||||
segmentit:
|
||||
optional: true
|
||||
|
||||
pixelmatch@5.3.0:
|
||||
resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==}
|
||||
hasBin: true
|
||||
@ -3734,6 +3846,9 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
|
||||
preval.macro@4.0.0:
|
||||
resolution: {integrity: sha512-sJJnE71X+MPr64CVD2AurmUj4JEDqbudYbStav3L9Xjcqm4AR0ymMm6sugw1mUmfI/7gw4JWA4JXo/k6w34crw==}
|
||||
|
||||
proc-log@2.0.1:
|
||||
resolution: {integrity: sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==}
|
||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||
@ -3936,6 +4051,9 @@ packages:
|
||||
sdp@3.2.0:
|
||||
resolution: {integrity: sha512-d7wDPgDV3DDiqulJjKiV2865wKsJ34YI+NDREbm+FySq6WuKOikwyNQcm+doLAZ1O6ltdO0SeKle2xMpN3Brgw==}
|
||||
|
||||
segmentit@2.0.3:
|
||||
resolution: {integrity: sha512-7mn2XL3OdTUQ+AhHz7SbgyxLTaQRzTWQNVwiK+UlTO8aePGbSwvKUzTwE4238+OUY9MoR6ksAg35zl8sfTunQQ==}
|
||||
|
||||
selderee@0.11.0:
|
||||
resolution: {integrity: sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==}
|
||||
|
||||
@ -4620,6 +4738,10 @@ packages:
|
||||
resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
yaml@1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
yaml@2.7.0:
|
||||
resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==}
|
||||
engines: {node: '>= 14'}
|
||||
@ -4643,6 +4765,9 @@ packages:
|
||||
youtubei.js@13.3.0:
|
||||
resolution: {integrity: sha512-tbl7rxltpgKoSsmfGUe9JqWUAzv6HFLqrOn0N85EbTn5DLt24EXrjClnXdxyr3PBARMJ3LC4vbll100a0ABsYw==}
|
||||
|
||||
zlibjs@0.3.1:
|
||||
resolution: {integrity: sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==}
|
||||
|
||||
zod@3.24.2:
|
||||
resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==}
|
||||
|
||||
@ -5732,6 +5857,8 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.20.0
|
||||
|
||||
'@types/parse-json@4.0.2': {}
|
||||
|
||||
'@types/plist@3.0.5':
|
||||
dependencies:
|
||||
'@types/node': 22.13.5
|
||||
@ -6075,6 +6202,10 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
async@2.6.4:
|
||||
dependencies:
|
||||
lodash: 4.17.21
|
||||
|
||||
async@3.2.6: {}
|
||||
|
||||
asynckit@0.4.0: {}
|
||||
@ -6102,6 +6233,18 @@ snapshots:
|
||||
parse5: 7.2.1
|
||||
validate-html-nesting: 1.2.2
|
||||
|
||||
babel-plugin-macros@2.8.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
cosmiconfig: 6.0.0
|
||||
resolve: 1.22.10
|
||||
|
||||
babel-plugin-preval@4.0.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
babel-plugin-macros: 2.8.0
|
||||
require-from-string: 2.0.2
|
||||
|
||||
babel-preset-solid@1.9.5(@babel/core@7.26.9):
|
||||
dependencies:
|
||||
'@babel/core': 7.26.9
|
||||
@ -6391,6 +6534,10 @@ snapshots:
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
|
||||
commander@1.1.1:
|
||||
dependencies:
|
||||
keypress: 0.1.0
|
||||
|
||||
commander@5.1.0: {}
|
||||
|
||||
commander@9.5.0:
|
||||
@ -6442,6 +6589,14 @@ snapshots:
|
||||
|
||||
core-util-is@1.0.3: {}
|
||||
|
||||
cosmiconfig@6.0.0:
|
||||
dependencies:
|
||||
'@types/parse-json': 4.0.2
|
||||
import-fresh: 3.3.1
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
yaml: 1.10.2
|
||||
|
||||
crc@3.8.0:
|
||||
dependencies:
|
||||
buffer: 5.7.1
|
||||
@ -6659,6 +6814,8 @@ snapshots:
|
||||
|
||||
dotenv@16.4.7: {}
|
||||
|
||||
doublearray@0.0.2: {}
|
||||
|
||||
dunder-proto@1.0.1:
|
||||
dependencies:
|
||||
call-bind-apply-helpers: 1.0.2
|
||||
@ -6833,6 +6990,10 @@ snapshots:
|
||||
|
||||
err-code@2.0.3: {}
|
||||
|
||||
error-ex@1.3.2:
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
|
||||
error-stack-parser-es@1.0.5: {}
|
||||
|
||||
es-abstract@1.23.9:
|
||||
@ -6905,6 +7066,8 @@ snapshots:
|
||||
isarray: 2.0.5
|
||||
stop-iteration-iterator: 1.1.0
|
||||
|
||||
es-hangul@2.2.4: {}
|
||||
|
||||
es-object-atoms@1.1.1:
|
||||
dependencies:
|
||||
es-errors: 1.3.0
|
||||
@ -7480,6 +7643,8 @@ snapshots:
|
||||
|
||||
graphemer@1.4.0: {}
|
||||
|
||||
hanja@1.1.4: {}
|
||||
|
||||
happy-dom@17.4.4:
|
||||
dependencies:
|
||||
webidl-conversions: 7.0.0
|
||||
@ -7650,6 +7815,8 @@ snapshots:
|
||||
call-bound: 1.0.3
|
||||
get-intrinsic: 1.3.0
|
||||
|
||||
is-arrayish@0.2.1: {}
|
||||
|
||||
is-async-function@2.1.1:
|
||||
dependencies:
|
||||
async-function: 1.0.0
|
||||
@ -7873,6 +8040,8 @@ snapshots:
|
||||
|
||||
json-buffer@3.0.1: {}
|
||||
|
||||
json-parse-even-better-errors@2.3.1: {}
|
||||
|
||||
json-schema-traverse@0.4.1: {}
|
||||
|
||||
json-schema-traverse@1.0.0: {}
|
||||
@ -7911,12 +8080,30 @@ snapshots:
|
||||
|
||||
keyboardevents-areequal@0.2.2: {}
|
||||
|
||||
keypress@0.1.0: {}
|
||||
|
||||
keyv@4.5.4:
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
|
||||
kuromoji@0.1.2(patch_hash=e4a08f477026373a427a51d9bedd268ee22a173850ede3750de32af5d241c28c):
|
||||
dependencies:
|
||||
async: 2.6.4
|
||||
doublearray: 0.0.2
|
||||
zlibjs: 0.3.1
|
||||
|
||||
kuroshiro-analyzer-kuromoji@1.1.0:
|
||||
dependencies:
|
||||
kuromoji: 0.1.2(patch_hash=e4a08f477026373a427a51d9bedd268ee22a173850ede3750de32af5d241c28c)
|
||||
|
||||
kuroshiro@1.2.0:
|
||||
dependencies:
|
||||
'@babel/runtime': 7.26.10
|
||||
|
||||
lazy-val@1.0.5: {}
|
||||
|
||||
lazy-var@2.2.2: {}
|
||||
|
||||
leac@0.6.0: {}
|
||||
|
||||
levn@0.4.1:
|
||||
@ -7930,6 +8117,8 @@ snapshots:
|
||||
dependencies:
|
||||
immediate: 3.0.6
|
||||
|
||||
lines-and-columns@1.2.4: {}
|
||||
|
||||
locate-path@6.0.0:
|
||||
dependencies:
|
||||
p-locate: 5.0.0
|
||||
@ -8347,6 +8536,13 @@ snapshots:
|
||||
xml-parse-from-string: 1.0.1
|
||||
xml2js: 0.6.2
|
||||
|
||||
parse-json@5.2.0:
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.26.2
|
||||
error-ex: 1.3.2
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
lines-and-columns: 1.2.4
|
||||
|
||||
parse5@7.2.1:
|
||||
dependencies:
|
||||
entities: 4.5.0
|
||||
@ -8380,6 +8576,8 @@ snapshots:
|
||||
|
||||
path-to-regexp@3.3.0: {}
|
||||
|
||||
path-type@4.0.0: {}
|
||||
|
||||
path-type@6.0.0: {}
|
||||
|
||||
pathe@2.0.3: {}
|
||||
@ -8413,6 +8611,12 @@ snapshots:
|
||||
|
||||
picomatch@4.0.2: {}
|
||||
|
||||
pinyin@4.0.0-alpha.2(segmentit@2.0.3):
|
||||
dependencies:
|
||||
commander: 1.1.1
|
||||
optionalDependencies:
|
||||
segmentit: 2.0.3
|
||||
|
||||
pixelmatch@5.3.0:
|
||||
dependencies:
|
||||
pngjs: 6.0.0
|
||||
@ -8456,6 +8660,10 @@ snapshots:
|
||||
|
||||
prettier@3.5.2: {}
|
||||
|
||||
preval.macro@4.0.0:
|
||||
dependencies:
|
||||
babel-plugin-preval: 4.0.0
|
||||
|
||||
proc-log@2.0.1: {}
|
||||
|
||||
proc-log@5.0.0: {}
|
||||
@ -8696,6 +8904,10 @@ snapshots:
|
||||
|
||||
sdp@3.2.0: {}
|
||||
|
||||
segmentit@2.0.3:
|
||||
dependencies:
|
||||
preval.macro: 4.0.0
|
||||
|
||||
selderee@0.11.0:
|
||||
dependencies:
|
||||
parseley: 0.12.1
|
||||
@ -9418,6 +9630,8 @@ snapshots:
|
||||
|
||||
yallist@5.0.0: {}
|
||||
|
||||
yaml@1.10.2: {}
|
||||
|
||||
yaml@2.7.0: {}
|
||||
|
||||
yargs-parser@21.1.1: {}
|
||||
@ -9446,4 +9660,6 @@ snapshots:
|
||||
tslib: 2.8.1
|
||||
undici: 5.28.5
|
||||
|
||||
zlibjs@0.3.1: {}
|
||||
|
||||
zod@3.24.2: {}
|
||||
|
||||
@ -756,6 +756,10 @@
|
||||
"label": "Make the lyrics perfectly synced",
|
||||
"tooltip": "Calculate to the milisecond the display of the next line (can have a small impact on performance)"
|
||||
},
|
||||
"romanization": {
|
||||
"label": "Romanize lyrics",
|
||||
"tooltip": "If the lyrics are in a different language, try to display a latin version."
|
||||
},
|
||||
"show-lyrics-even-if-inexact": {
|
||||
"label": "Show lyrics even if inexact",
|
||||
"tooltip": "If the song is not found, the plugin tries again with a different search query.\nThe result from the second attempt may not be exact."
|
||||
|
||||
@ -825,7 +825,7 @@ app.whenReady().then(async () => {
|
||||
|
||||
// Optimized for Mac OS X
|
||||
if (is.macOS() && !config.get('options.appVisible')) {
|
||||
app.dock.hide();
|
||||
app.dock?.hide();
|
||||
}
|
||||
|
||||
let forceQuit = false;
|
||||
|
||||
@ -20,7 +20,8 @@ export default createPlugin({
|
||||
showTimeCodes: false,
|
||||
defaultTextString: '♪',
|
||||
lineEffect: 'fancy',
|
||||
} satisfies SyncedLyricsPluginConfig,
|
||||
romanization: true,
|
||||
} satisfies SyncedLyricsPluginConfig as SyncedLyricsPluginConfig,
|
||||
|
||||
menu,
|
||||
renderer,
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { MenuItemConstructorOptions } from 'electron';
|
||||
|
||||
import { t } from '@/i18n';
|
||||
|
||||
import type { MenuItemConstructorOptions } from 'electron';
|
||||
import type { MenuContext } from '@/types/contexts';
|
||||
import type { SyncedLyricsPluginConfig } from './types';
|
||||
|
||||
@ -136,6 +135,17 @@ export const menu = async (
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: t('plugins.synced-lyrics.menu.romanization.label'),
|
||||
toolTip: t('plugins.synced-lyrics.menu.romanization.tooltip'),
|
||||
type: 'checkbox',
|
||||
checked: config.romanization,
|
||||
click(item) {
|
||||
ctx.setConfig({
|
||||
romanization: item.checked,
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: t('plugins.synced-lyrics.menu.show-time-codes.label'),
|
||||
toolTip: t('plugins.synced-lyrics.menu.show-time-codes.tooltip'),
|
||||
|
||||
@ -30,15 +30,16 @@ export class LyricsGenius implements LyricProvider {
|
||||
title: titleA,
|
||||
primary_artist: { name: artistA },
|
||||
},
|
||||
},
|
||||
{
|
||||
}, {
|
||||
result: {
|
||||
title: titleB,
|
||||
primary_artist: { name: artistB },
|
||||
},
|
||||
}) => {
|
||||
const pointsA = (titleA === title ? 1 : 0) + (artistA.includes(artist) ? 1 : 0);
|
||||
const pointsB = (titleB === title ? 1 : 0) + (artistB.includes(artist) ? 1 : 0);
|
||||
const pointsA = (titleA === title ? 1 : 0) +
|
||||
(artistA.includes(artist) ? 1 : 0);
|
||||
const pointsB = (titleB === title ? 1 : 0) +
|
||||
(artistB.includes(artist) ? 1 : 0);
|
||||
|
||||
return pointsB - pointsA;
|
||||
},
|
||||
@ -51,14 +52,21 @@ export class LyricsGenius implements LyricProvider {
|
||||
|
||||
const { result: { path } } = closestHit;
|
||||
|
||||
const html = await fetch(`${this.baseUrl}${path}`).then((res) => res.text());
|
||||
const html = await fetch(`${this.baseUrl}${path}`).then((res) =>
|
||||
res.text()
|
||||
);
|
||||
const doc = this.domParser.parseFromString(html, 'text/html');
|
||||
|
||||
const preloadedStateScript = Array.prototype.find.call(doc.querySelectorAll('script'), (script: HTMLScriptElement) => {
|
||||
return script.textContent?.includes('window.__PRELOADED_STATE__');
|
||||
}) as HTMLScriptElement;
|
||||
const preloadedStateScript = Array.prototype.find.call(
|
||||
doc.querySelectorAll('script'),
|
||||
(script: HTMLScriptElement) => {
|
||||
return script.textContent?.includes('window.__PRELOADED_STATE__');
|
||||
},
|
||||
) as HTMLScriptElement;
|
||||
|
||||
const preloadedState = preloadedStateScript.textContent?.match(preloadedStateRegex)?.[1]?.replace(/\\"/g, '"');
|
||||
const preloadedState = preloadedStateScript.textContent?.match(
|
||||
preloadedStateRegex,
|
||||
)?.[1]?.replace(/\\"/g, '"');
|
||||
|
||||
const lyricsHtml = preloadedState?.match(preloadHtmlRegex)?.[1]
|
||||
?.replace(/\\\//g, '/')
|
||||
@ -67,12 +75,19 @@ export class LyricsGenius implements LyricProvider {
|
||||
?.replace(/\\'/g, "'")
|
||||
?.replace(/\\"/g, '"');
|
||||
|
||||
if (!lyricsHtml) throw new Error('Failed to extract lyrics from preloaded state.');
|
||||
const hasUnreleasedPlaceholder = preloadedState &&
|
||||
/lyricsPlaceholderReason.{1,5}unreleased/.test(preloadedState);
|
||||
if (!lyricsHtml) {
|
||||
if (hasUnreleasedPlaceholder) return null;
|
||||
throw new Error('Failed to extract lyrics from preloaded state.');
|
||||
}
|
||||
|
||||
const lyricsDoc = this.domParser.parseFromString(lyricsHtml, 'text/html');
|
||||
const lyrics = lyricsDoc.body.innerText;
|
||||
|
||||
if (lyrics.trim().toLowerCase().replace(/[[\]]/g, '') === 'instrumental') return null;
|
||||
if (lyrics.trim().toLowerCase().replace(/[[\]]/g, '') === 'instrumental') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
title: closestHit.result.title,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { createSignal, For, Match, Show, Switch } from 'solid-js';
|
||||
import { createEffect, createSignal, For, Match, Show, Switch } from 'solid-js';
|
||||
|
||||
import { SyncedLine } from './SyncedLine';
|
||||
|
||||
@ -6,6 +6,7 @@ import { ErrorDisplay } from './ErrorDisplay';
|
||||
import { LoadingKaomoji } from './LoadingKaomoji';
|
||||
import { PlainLyrics } from './PlainLyrics';
|
||||
|
||||
import { hasJapaneseInString, hasKoreanInString } from '../utils';
|
||||
import { currentLyrics, lyricsStore } from '../../providers';
|
||||
|
||||
export const [debugInfo, setDebugInfo] = createSignal<string>();
|
||||
@ -13,6 +14,20 @@ export const [currentTime, setCurrentTime] = createSignal<number>(-1);
|
||||
|
||||
// prettier-ignore
|
||||
export const LyricsContainer = () => {
|
||||
const [hasJapanese, setHasJapanese] = createSignal<boolean>(false);
|
||||
const [hasKorean, setHasKorean] = createSignal<boolean>(false);
|
||||
|
||||
createEffect(() => {
|
||||
const data = currentLyrics()?.data;
|
||||
if (data) {
|
||||
setHasKorean(hasKoreanInString(data));
|
||||
setHasJapanese(hasJapaneseInString(data));
|
||||
} else {
|
||||
setHasKorean(false);
|
||||
setHasJapanese(false);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="lyric-container">
|
||||
<Switch>
|
||||
@ -42,12 +57,12 @@ export const LyricsContainer = () => {
|
||||
<Switch>
|
||||
<Match when={currentLyrics().data?.lines}>
|
||||
<For each={currentLyrics().data?.lines}>
|
||||
{(item) => <SyncedLine line={item} />}
|
||||
{(item) => <SyncedLine line={item} hasJapanese={hasJapanese()} hasKorean={hasKorean()} />}
|
||||
</For>
|
||||
</Match>
|
||||
|
||||
<Match when={currentLyrics().data?.lyrics}>
|
||||
<PlainLyrics lyrics={currentLyrics().data?.lyrics!} />
|
||||
<PlainLyrics lyrics={currentLyrics().data!.lyrics!} hasJapanese={hasJapanese()} hasKorean={hasKorean()} />
|
||||
</Match>
|
||||
</Switch>
|
||||
</div>
|
||||
|
||||
@ -1,28 +1,91 @@
|
||||
import { createMemo, For } from 'solid-js';
|
||||
import { createEffect, createMemo, createSignal, For, Show } from 'solid-js';
|
||||
|
||||
import {
|
||||
canonicalize,
|
||||
romanizeChinese,
|
||||
romanizeHangul,
|
||||
romanizeJapanese,
|
||||
romanizeJapaneseOrHangul,
|
||||
simplifyUnicode,
|
||||
} from '../utils';
|
||||
import { config } from '../renderer';
|
||||
|
||||
interface PlainLyricsProps {
|
||||
lyrics: string;
|
||||
hasJapanese: boolean;
|
||||
hasKorean: boolean;
|
||||
}
|
||||
|
||||
export const PlainLyrics = (props: PlainLyricsProps) => {
|
||||
const lines = createMemo(() => props.lyrics.split('\n'));
|
||||
const lines = props.lyrics.split('\n').filter((line) => line.trim());
|
||||
const [romanizedLines, setRomanizedLines] = createSignal<
|
||||
Record<string, string>
|
||||
>({});
|
||||
|
||||
const combinedLines = createMemo(() => {
|
||||
const out = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
out.push([lines[i], romanizedLines()[i]]);
|
||||
}
|
||||
|
||||
return out;
|
||||
});
|
||||
|
||||
createEffect(async () => {
|
||||
if (!config()?.romanization) return;
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let romanized: string;
|
||||
|
||||
if (props.hasJapanese) {
|
||||
if (props.hasKorean)
|
||||
romanized = await romanizeJapaneseOrHangul(lines[i]);
|
||||
else romanized = await romanizeJapanese(lines[i]);
|
||||
} else if (props.hasKorean) romanized = romanizeHangul(lines[i]);
|
||||
else romanized = romanizeChinese(lines[i]);
|
||||
|
||||
setRomanizedLines((prev) => ({
|
||||
...prev,
|
||||
[i]: canonicalize(romanized),
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<div class="plain-lyrics">
|
||||
<For each={lines()}>
|
||||
{(line) => {
|
||||
if (line.trim() === '') {
|
||||
return <br />;
|
||||
} else {
|
||||
return (
|
||||
<For each={combinedLines()}>
|
||||
{([line, romanized]) => {
|
||||
return (
|
||||
<div
|
||||
class={`${
|
||||
line.match(/^\[.+\]$/s) ? 'lrc-header' : ''
|
||||
} text-lyrics description ytmusic-description-shelf-renderer`}
|
||||
style={{
|
||||
'display': 'flex',
|
||||
'flex-direction': 'column',
|
||||
}}
|
||||
>
|
||||
<yt-formatted-string
|
||||
class="text-lyrics description ytmusic-description-shelf-renderer"
|
||||
text={{
|
||||
runs: [{ text: line }],
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
<Show
|
||||
when={
|
||||
config()?.romanization &&
|
||||
simplifyUnicode(line) !== simplifyUnicode(romanized)
|
||||
}
|
||||
>
|
||||
<yt-formatted-string
|
||||
class="romaji"
|
||||
text={{
|
||||
runs: [{ text: romanized }],
|
||||
}}
|
||||
/>
|
||||
</Show>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
</div>
|
||||
|
||||
@ -1,22 +1,33 @@
|
||||
import { createEffect, createMemo, For } from 'solid-js';
|
||||
import { createEffect, createMemo, For, Show, createSignal } from 'solid-js';
|
||||
|
||||
import { currentTime } from './LyricsContainer';
|
||||
|
||||
import { config } from '../renderer';
|
||||
import { _ytAPI } from '..';
|
||||
|
||||
import {
|
||||
canonicalize,
|
||||
romanizeChinese,
|
||||
romanizeHangul,
|
||||
romanizeJapanese,
|
||||
romanizeJapaneseOrHangul,
|
||||
simplifyUnicode,
|
||||
} from '../utils';
|
||||
|
||||
import type { LineLyrics } from '../../types';
|
||||
|
||||
interface SyncedLineProps {
|
||||
line: LineLyrics;
|
||||
hasJapanese: boolean;
|
||||
hasKorean: boolean;
|
||||
}
|
||||
|
||||
export const SyncedLine = ({ line }: SyncedLineProps) => {
|
||||
export const SyncedLine = (props: SyncedLineProps) => {
|
||||
const status = createMemo(() => {
|
||||
const current = currentTime();
|
||||
|
||||
if (line.timeInMs >= current) return 'upcoming';
|
||||
if (current - line.timeInMs >= line.duration) return 'previous';
|
||||
if (props.line.timeInMs >= current) return 'upcoming';
|
||||
if (current - props.line.timeInMs >= props.line.duration) return 'previous';
|
||||
return 'current';
|
||||
});
|
||||
|
||||
@ -28,8 +39,28 @@ export const SyncedLine = ({ line }: SyncedLineProps) => {
|
||||
});
|
||||
|
||||
const text = createMemo(() => {
|
||||
if (line.text.trim()) return line.text;
|
||||
return config()?.defaultTextString ?? '';
|
||||
if (!props.line.text.trim()) {
|
||||
return config()?.defaultTextString ?? '';
|
||||
}
|
||||
|
||||
return props.line.text;
|
||||
});
|
||||
|
||||
const [romanization, setRomanization] = createSignal('');
|
||||
|
||||
createEffect(async () => {
|
||||
if (!config()?.romanization) return;
|
||||
|
||||
const input = canonicalize(text());
|
||||
|
||||
let result: string;
|
||||
if (props.hasJapanese) {
|
||||
if (props.hasKorean) result = await romanizeJapaneseOrHangul(input);
|
||||
else result = await romanizeJapanese(input);
|
||||
} else if (props.hasKorean) result = romanizeHangul(input);
|
||||
else result = romanizeChinese(input);
|
||||
|
||||
setRomanization(canonicalize(result));
|
||||
});
|
||||
|
||||
if (!text()) {
|
||||
@ -47,35 +78,79 @@ export const SyncedLine = ({ line }: SyncedLineProps) => {
|
||||
ref={ref}
|
||||
class={`synced-line ${status()}`}
|
||||
onClick={() => {
|
||||
_ytAPI?.seekTo(line.timeInMs / 1000);
|
||||
_ytAPI?.seekTo(props.line.timeInMs / 1000);
|
||||
}}
|
||||
>
|
||||
<div dir="auto" class="text-lyrics description ytmusic-description-shelf-renderer">
|
||||
<div dir="auto" class="description ytmusic-description-shelf-renderer">
|
||||
<yt-formatted-string
|
||||
text={{
|
||||
runs: [{ text: config()?.showTimeCodes ? `[${line.time}] ` : '' }],
|
||||
runs: [
|
||||
{ text: config()?.showTimeCodes ? `[${props.line.time}] ` : '' },
|
||||
],
|
||||
}}
|
||||
/>
|
||||
|
||||
<For each={text().split(' ')}>
|
||||
{(word, index) => {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
'transition-delay': `${index() * 0.05}s`,
|
||||
'animation-delay': `${index() * 0.05}s`,
|
||||
'--lyrics-duration:': `${line.duration / 1000}s;`,
|
||||
}}
|
||||
>
|
||||
<yt-formatted-string
|
||||
text={{
|
||||
runs: [{ text: `${word} ` }],
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
class="text-lyrics"
|
||||
ref={(div: HTMLDivElement) => {
|
||||
// TODO: Investigate the animation, even though the duration is properly set, all lines have the same animation duration
|
||||
div.style.setProperty(
|
||||
'--lyrics-duration',
|
||||
`${props.line.duration / 1000}s`,
|
||||
'important',
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
style={{ 'display': 'flex', 'flex-direction': 'column' }}
|
||||
>
|
||||
<span>
|
||||
<For each={text().split(' ')}>
|
||||
{(word, index) => {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
'transition-delay': `${index() * 0.05}s`,
|
||||
'animation-delay': `${index() * 0.05}s`,
|
||||
}}
|
||||
>
|
||||
<yt-formatted-string
|
||||
text={{
|
||||
runs: [{ text: `${word} ` }],
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
</span>
|
||||
|
||||
<Show
|
||||
when={
|
||||
config()?.romanization &&
|
||||
simplifyUnicode(text()) !== simplifyUnicode(romanization())
|
||||
}
|
||||
>
|
||||
<span class="romaji">
|
||||
<For each={romanization().split(' ')}>
|
||||
{(word, index) => {
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
'transition-delay': `${index() * 0.05}s`,
|
||||
'animation-delay': `${index() * 0.05}s`,
|
||||
}}
|
||||
>
|
||||
<yt-formatted-string
|
||||
text={{
|
||||
runs: [{ text: `${word} ` }],
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
}}
|
||||
</For>
|
||||
</span>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,8 +1,20 @@
|
||||
import { render } from 'solid-js/web';
|
||||
|
||||
import KuromojiAnalyzer from 'kuroshiro-analyzer-kuromoji';
|
||||
import Kuroshiro from 'kuroshiro';
|
||||
|
||||
import { romanize as esHangulRomanize } from 'es-hangul';
|
||||
import hanja from 'hanja';
|
||||
|
||||
import pinyin from 'pinyin/esm/pinyin';
|
||||
|
||||
import { lazy } from 'lazy-var';
|
||||
|
||||
import { waitForElement } from '@/utils/wait-for-element';
|
||||
import { LyricsRenderer, setIsVisible } from './renderer';
|
||||
|
||||
import type { LyricResult } from '@/plugins/synced-lyrics/types';
|
||||
|
||||
export const selectors = {
|
||||
head: '#tabsContent > .tab-header:nth-of-type(2)',
|
||||
body: {
|
||||
@ -33,3 +45,148 @@ export const tabStates: Record<string, () => void> = {
|
||||
setIsVisible(false);
|
||||
},
|
||||
};
|
||||
|
||||
export const canonicalize = (text: string) => {
|
||||
return (
|
||||
text
|
||||
// `hi there` => `hi there`
|
||||
.replaceAll(/\s+/g, ' ')
|
||||
|
||||
// `( a )` => `(a)`
|
||||
.replaceAll(/([([]) ([^ ])/g, (_, symbol, a) => `${symbol}${a}`)
|
||||
.replaceAll(/([^ ]) ([)\]])/g, (_, a, symbol) => `${a}${symbol}`)
|
||||
|
||||
// `can ' t` => `can't`
|
||||
.replaceAll(
|
||||
/([Ii]) (') ([^ ])|(n) (') (t)(?= |$)|(t) (') (s)|([^ ]) (') (re)|([^ ]) (') (ve)|([^ ]) (-) ([^ ])/g,
|
||||
(m, ...groups) => {
|
||||
for (let i = 0; i < groups.length; i += 3) {
|
||||
if (groups[i]) {
|
||||
return groups.slice(i, i + 3).join('');
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
},
|
||||
)
|
||||
// `Stayin ' still` => `Stayin' still`
|
||||
.replaceAll(/in ' ([^ ])/g, (_, char) => `in' ${char}`)
|
||||
.replaceAll("in ',", "in',")
|
||||
|
||||
.replaceAll(", ' cause", ", 'cause")
|
||||
|
||||
// `hi , there` => `hi, there`
|
||||
.replaceAll(/([^ ]) ([.,!?])/g, (_, a, symbol) => `${a}${symbol}`)
|
||||
|
||||
// `hi " there "` => `hi "there"`
|
||||
.replaceAll(
|
||||
/"([^"]+)"/g,
|
||||
(_, content) =>
|
||||
`"${typeof content === 'string' ? content.trim() : content}"`,
|
||||
)
|
||||
.trim()
|
||||
);
|
||||
};
|
||||
|
||||
export const simplifyUnicode = (text?: string) =>
|
||||
text
|
||||
? text
|
||||
.replaceAll(/\u0020|\u00A0|[\u2000-\u200A]|\u202F|\u205F|\u3000/g, ' ')
|
||||
.trim()
|
||||
: text;
|
||||
|
||||
// Japanese Shinjitai
|
||||
const shinjitai = [
|
||||
20055, 20081, 20120, 20124, 20175, 26469, 20341, 20206, 20253, 20605, 20385,
|
||||
20537, 20816, 20001, 20869, 23500, 28092, 20956, 21104, 21091, 21092, 21172,
|
||||
21234, 21169, 21223, 21306, 24059, 21363, 21442, 21782, 21336, 22107, 21427,
|
||||
22065, 22287, 22269, 22258, 20870, 22259, 22243, 37326, 23597, 22679, 22549,
|
||||
22311, 22593, 22730, 22732, 22766, 22769, 23551, 22885, 22888, 23330, 23398,
|
||||
23517, 23455, 20889, 23515, 23453, 23558, 23554, 23550, 23626, 23631, 23646,
|
||||
23792, 23777, 23798, 23731, 24012, 24035, 24111, 24182, 24259, 24195, 24193,
|
||||
24382, 24357, 24367, 24452, 24467, 24500, 24499, 24658, 24693, 24746, 24745,
|
||||
24910, 24808, 24540, 25040, 24651, 25126, 25135, 25144, 25147, 25173, 25244,
|
||||
25309, 25375, 25407, 25522, 25531, 25594, 25436, 25246, 25731, 25285, 25312,
|
||||
25369, 25313, 25666, 25785, 21454, 21177, 21465, 21189, 25968, 26029, 26179,
|
||||
26217, 26172, 26278, 26241, 26365, 20250, 26465, 26719, 26628, 27097, 27010,
|
||||
27005, 27004, 26530, 27096, 27178, 26727, 26908, 26716, 27177, 27431, 27475,
|
||||
27497, 27508, 24112, 27531, 27579, 27572, 27598, 27671, 28169, 28057, 27972,
|
||||
27973, 28167, 28179, 28201, 28382, 28288, 28300, 28508, 28171, 27810, 28287,
|
||||
28168, 27996, 27818, 28381, 28716, 28286, 28948, 28783, 28988, 21942, 28809,
|
||||
20105, 28858, 29344, 29366, 29421, 22888, 29420, 29471, 29539, 29486, 24321,
|
||||
29942, 30011, 24403, 30067, 30185, 30196, 30330, 26479, 30423, 23613, 30495,
|
||||
30740, 30741, 30783, 31192, 31108, 31109, 31036, 31074, 31095, 31216, 31282,
|
||||
38964, 31298, 31311, 31331, 31363, 20006, 31883, 31992, 32076, 32209, 32210,
|
||||
32257, 30476, 32294, 32207, 32333, 32260, 32117, 32331, 32153, 32154, 32330,
|
||||
27424, 32566, 22768, 32884, 31899, 33075, 32966, 33235, 21488, 19982, 26087,
|
||||
33398, 33624, 33550, 33804, 19975, 33931, 22290, 34219, 34101, 33464, 34220,
|
||||
33446, 20966, 34394, 21495, 34509, 34411, 34635, 34453, 34542, 34907, 35013,
|
||||
35090, 35226, 35239, 35251, 35302, 35617, 35388, 35379, 35465, 35501, 22793,
|
||||
35698, 35715, 35914, 33398, 20104, 24336, 22770, 38972, 36059, 36341, 36527,
|
||||
36605, 36620, 36578, 24321, 36766, 24321, 36965, 36883, 36933, 36794, 37070,
|
||||
37111, 37204, 21307, 37284, 37271, 37304, 37320, 37682, 37549, 37676, 37806,
|
||||
37444, 37619, 37489, 38306, 38501, 38543, 38522, 38560, 21452, 38609, 35207,
|
||||
38666, 38745, 39003, 38997, 32763, 20313, 39173, 39366, 39442, 39366, 39443,
|
||||
39365, 39620, 20307, 39658, 38360, 40335, 40206, 40568, 22633, 40614, 40633,
|
||||
40634, 40644, 40658, 40665, 28857, 20826, 25993, 25998, 27503, 40802, 31452,
|
||||
20096,
|
||||
].map((codePoint) => String.fromCodePoint(codePoint));
|
||||
const shinjitaiRegex = new RegExp(`[${shinjitai.join('')}]`);
|
||||
|
||||
const kuroshiro = lazy(async () => {
|
||||
const _kuroshiro = new Kuroshiro();
|
||||
await _kuroshiro.init(
|
||||
new KuromojiAnalyzer({
|
||||
dictPath: 'https://cdn.jsdelivr.net/npm/kuromoji@0.1.2/dict/',
|
||||
}),
|
||||
);
|
||||
return _kuroshiro;
|
||||
});
|
||||
|
||||
const hasJapanese = (lines: string[]) =>
|
||||
lines.some(
|
||||
(line) => Kuroshiro.Util.hasKana(line) || shinjitaiRegex.test(line),
|
||||
);
|
||||
|
||||
// tests for Hangul characters, sufficient for our use case
|
||||
const hasKorean = (lines: string[]) =>
|
||||
lines.some((line) => /[ㄱ-ㅎㅏ-ㅣ가-힣]+/.test(line));
|
||||
|
||||
export const hasJapaneseInString = (lyric: LyricResult) => {
|
||||
if (!lyric || (!lyric.lines && !lyric.lyrics)) return false;
|
||||
const lines = Array.isArray(lyric.lines)
|
||||
? lyric.lines.map(({ text }) => text)
|
||||
: lyric.lyrics!.split('\n');
|
||||
return hasJapanese(lines);
|
||||
};
|
||||
|
||||
export const hasKoreanInString = (lyric: LyricResult) => {
|
||||
if (!lyric || (!lyric.lines && !lyric.lyrics)) return false;
|
||||
|
||||
const lines = Array.isArray(lyric.lines)
|
||||
? lyric.lines.map(({ text }) => text)
|
||||
: lyric.lyrics!.split('\n');
|
||||
|
||||
return hasKorean(lines);
|
||||
};
|
||||
|
||||
export const romanizeJapanese = async (line: string) =>
|
||||
(await kuroshiro.get()).convert(line, {
|
||||
to: 'romaji',
|
||||
mode: 'spaced',
|
||||
});
|
||||
|
||||
export const romanizeHangul = (line: string) =>
|
||||
esHangulRomanize(hanja.translate(line, 'SUBSTITUTION'));
|
||||
|
||||
export const romanizeJapaneseOrHangul = async (line: string) =>
|
||||
romanizeHangul(await romanizeJapanese(line));
|
||||
|
||||
export const romanizeChinese = (line: string) =>
|
||||
pinyin(line, {
|
||||
heteronym: true,
|
||||
segment: true,
|
||||
group: true,
|
||||
})
|
||||
.flat()
|
||||
.join(' ');
|
||||
|
||||
@ -8,6 +8,17 @@
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
/* Hide the scrollbar in the lyrics-tab */
|
||||
#tab-renderer[page-type='MUSIC_PAGE_TYPE_TRACK_LYRICS'] {
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
@property --lyrics-duration {
|
||||
syntax: '<time>';
|
||||
inherits: false;
|
||||
initial-value: 2s;
|
||||
}
|
||||
|
||||
/* Variables are overridden by selected line effect */
|
||||
:root {
|
||||
/* Layout */
|
||||
@ -15,8 +26,9 @@
|
||||
--lyrics-padding: 0;
|
||||
|
||||
/* Typography */
|
||||
--lyrics-font-family: Satoshi, Avenir, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell,
|
||||
Open Sans, Helvetica Neue, sans-serif;
|
||||
--lyrics-font-family: Satoshi, Avenir, -apple-system, BlinkMacSystemFont,
|
||||
Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue,
|
||||
sans-serif;
|
||||
--lyrics-font-size: clamp(1.4rem, 1.1vmax, 3rem);
|
||||
--lyrics-line-height: var(--ytmusic-body-line-height);
|
||||
--lyrics-width: 100%;
|
||||
@ -33,12 +45,15 @@
|
||||
--lyrics-active-scale: 1;
|
||||
--lyrics-active-offset: 0;
|
||||
|
||||
--lyrics-duration: 2s;
|
||||
|
||||
/* Animations */
|
||||
--lyrics-animations: lyrics-glow var(--lyrics-glow-duration) forwards, lyrics-wobble var(--lyrics-wobble-duration) forwards;
|
||||
--lyrics-animations: lyrics-glow var(--lyrics-glow-duration) forwards,
|
||||
lyrics-wobble var(--lyrics-wobble-duration) forwards;
|
||||
--lyrics-scale-duration: 0.166s;
|
||||
--lyrics-opacity-transition: 0.33s;
|
||||
--lyrics-glow-duration: var(--lyrics-duration, 2s);
|
||||
--lyrics-wobble-duration: calc(var(--lyrics-duration, 2s) / 2);
|
||||
--lyrics-glow-duration: var(--lyrics-duration);
|
||||
--lyrics-wobble-duration: calc(var(--lyrics-duration) / 2);
|
||||
|
||||
/* Colors */
|
||||
--glow-color: rgba(255, 255, 255, 0.5);
|
||||
@ -56,9 +71,29 @@
|
||||
.synced-line {
|
||||
width: var(--lyrics-width, 100%);
|
||||
|
||||
& > .text-lyrics {
|
||||
& .text-lyrics {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
& .text-lyrics > .romaji {
|
||||
color: var(--ytmusic-text-secondary) !important;
|
||||
font-size: calc(var(--lyrics-font-size) * 0.7) !important;
|
||||
font-style: italic !important;
|
||||
}
|
||||
}
|
||||
|
||||
.plain-lyrics .romaji {
|
||||
color: var(--ytmusic-text-secondary) !important;
|
||||
font-size: calc(var(--lyrics-font-size) * 0.7) !important;
|
||||
font-style: italic !important;
|
||||
}
|
||||
|
||||
.plain-lyrics .lrc-header {
|
||||
color: var(--ytmusic-color-grey5) !important;
|
||||
scale: 0.9;
|
||||
height: fit-content;
|
||||
padding: 0;
|
||||
padding-block: 0.2em;
|
||||
}
|
||||
|
||||
.synced-lyrics {
|
||||
@ -83,9 +118,7 @@
|
||||
padding-bottom: var(--lyrics-padding);
|
||||
scale: var(--lyrics-inactive-scale);
|
||||
translate: var(--lyrics-inactive-offset);
|
||||
transition:
|
||||
scale var(--lyrics-scale-duration),
|
||||
translate 0.3s ease-in-out;
|
||||
transition: scale var(--lyrics-scale-duration), translate 0.3s ease-in-out;
|
||||
|
||||
display: block;
|
||||
text-align: left;
|
||||
@ -93,30 +126,24 @@
|
||||
transform-origin: 0 50%;
|
||||
}
|
||||
|
||||
.text-lyrics > span {
|
||||
.text-lyrics > span > span {
|
||||
display: inline-block;
|
||||
white-space: pre-wrap;
|
||||
opacity: var(--lyrics-inactive-opacity);
|
||||
transition: opacity var(--lyrics-opacity-transition);
|
||||
}
|
||||
|
||||
.previous > .text-lyrics {
|
||||
}
|
||||
|
||||
.current > .text-lyrics {
|
||||
.current .text-lyrics {
|
||||
font-weight: var(--lyrics-active-font-weight) !important;
|
||||
scale: var(--lyrics-active-scale);
|
||||
translate: var(--lyrics-active-offset);
|
||||
}
|
||||
|
||||
.current > .text-lyrics > span {
|
||||
.current .text-lyrics > span > span {
|
||||
opacity: var(--lyrics-active-opacity);
|
||||
animation: var(--lyrics-animations);
|
||||
}
|
||||
|
||||
.upcoming > .text-lyrics {
|
||||
}
|
||||
|
||||
.lyrics-renderer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { SongInfo } from '@/providers/song-info';
|
||||
import type { SongInfo } from '@/providers/song-info';
|
||||
|
||||
export type SyncedLyricsPluginConfig = {
|
||||
enabled: boolean;
|
||||
@ -7,6 +7,7 @@ export type SyncedLyricsPluginConfig = {
|
||||
defaultTextString: string;
|
||||
showLyricsEvenIfInexact: boolean;
|
||||
lineEffect: LineEffect;
|
||||
romanization: boolean;
|
||||
};
|
||||
|
||||
export type LineLyricsStatus = 'previous' | 'current' | 'upcoming';
|
||||
|
||||
12
src/ts-declarations/kuroshiro-analyzer-kuromoji.d.ts
vendored
Normal file
12
src/ts-declarations/kuroshiro-analyzer-kuromoji.d.ts
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
// Stolen from https://github.com/hexenq/kuroshiro-analyzer-kuromoji/pull/7
|
||||
// Credit goes to https://github.com/ALOHACREPES345
|
||||
|
||||
declare class KuromojiAnalyzer {
|
||||
constructor(dictPath?: { dictPath: string });
|
||||
init(): Promise<void>;
|
||||
parse(str: string): Promise<unknown>;
|
||||
}
|
||||
|
||||
declare module 'kuroshiro-analyzer-kuromoji' {
|
||||
export = KuromojiAnalyzer;
|
||||
}
|
||||
40
src/ts-declarations/kuroshiro.d.ts
vendored
Normal file
40
src/ts-declarations/kuroshiro.d.ts
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
// Stolen from https://github.com/hexenq/kuroshiro/pull/93
|
||||
// Credit goes to https://github.com/ALOHACREPES345 and https://github.com/lcsvcn
|
||||
declare class Kuroshiro {
|
||||
constructor();
|
||||
_analyzer: import('kuroshiro-analyzer-kuromoji') | null;
|
||||
init(analyzer: import('kuroshiro-analyzer-kuromoji')): Promise<void>;
|
||||
convert(
|
||||
str: string,
|
||||
options?: {
|
||||
to?: 'hiragana' | 'katakana' | 'romaji';
|
||||
mode?: 'normal' | 'spaced' | 'okurigana' | 'furigana';
|
||||
romajiSystem?: 'nippon' | 'passport' | 'hepburn';
|
||||
delimiter_start?: string;
|
||||
delimiter_end?: string;
|
||||
},
|
||||
): Promise<string>;
|
||||
|
||||
static Util: {
|
||||
isHiragana: (ch: string) => boolean;
|
||||
isKatakana: (ch: string) => boolean;
|
||||
isKana: (ch: string) => boolean;
|
||||
isKanji: (ch: string) => boolean;
|
||||
isJapanese: (ch: string) => boolean;
|
||||
hasHiragana: (str: string) => boolean;
|
||||
hasKatakana: (str: string) => boolean;
|
||||
hasKana: (str: string) => boolean;
|
||||
hasKanji: (str: string) => boolean;
|
||||
hasJapanese: (str: string) => boolean;
|
||||
kanaToHiragana: (str: string) => string;
|
||||
kanaToKatakana: (str: string) => string;
|
||||
kanaToRomaji: (
|
||||
str: string,
|
||||
system: 'nippon' | 'passport' | 'hepburn',
|
||||
) => string;
|
||||
};
|
||||
}
|
||||
|
||||
declare module 'kuroshiro' {
|
||||
export = Kuroshiro;
|
||||
}
|
||||
Reference in New Issue
Block a user