refactor: upgrade

This commit is contained in:
Kieran 2023-12-04 11:01:56 +00:00
parent 01eaf9996c
commit e2714c4274
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
105 changed files with 1894 additions and 4698 deletions

View File

@ -1,7 +1,15 @@
module.exports = {
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint"],
plugins: ["@typescript-eslint", "formatjs"],
rules: {
"formatjs/enforce-id": [
"error",
{
idInterpolationPattern: "[sha512:contenthash:base64:6]",
},
],
},
root: true,
ignorePatterns: ["build/", "*.test.ts", "*.js"],
env: {
@ -10,10 +18,4 @@ module.exports = {
commonjs: true,
node: false,
},
rules: {
"@typescript-eslint/no-non-null-assertion": "error",
"require-await": "error",
eqeqeq: "error",
"object-shorthand": "warn",
},
};

4
.gitignore vendored
View File

@ -29,4 +29,6 @@ yarn-error.log*
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
!.yarn/versions
dev-dist/

View File

@ -1,4 +1,6 @@
.yarn/
.vscode/
node_modules/
build/
build/
dist/
dev-dist/

View File

@ -1,3 +1,7 @@
{
"recommendations": ["arcanis.vscode-zipfs", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
"recommendations": [
"arcanis.vscode-zipfs",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";

View File

@ -0,0 +1,20 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require eslint/use-at-your-own-risk
require(absPnpApiPath).setup();
}
}
// Defer to the real eslint/use-at-your-own-risk your application uses
module.exports = absRequire(`eslint/use-at-your-own-risk`);

View File

@ -2,5 +2,13 @@
"name": "eslint",
"version": "8.48.0-sdk",
"main": "./lib/api.js",
"type": "commonjs"
"type": "commonjs",
"bin": {
"eslint": "./bin/eslint.js"
},
"exports": {
"./package.json": "./package.json",
".": "./lib/api.js",
"./use-at-your-own-risk": "./lib/unsupported-api.js"
}
}

20
.yarn/sdks/prettier/bin-prettier.js vendored Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require prettier/bin-prettier.js
require(absPnpApiPath).setup();
}
}
// Defer to the real prettier/bin-prettier.js your application uses
module.exports = absRequire(`prettier/bin-prettier.js`);

6
.yarn/sdks/prettier/index.js vendored Executable file → Normal file
View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../.pnp.cjs";

View File

@ -2,5 +2,6 @@
"name": "prettier",
"version": "2.8.8-sdk",
"main": "./index.js",
"type": "commonjs"
"type": "commonjs",
"bin": "./bin-prettier.js"
}

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
@ -14,18 +14,16 @@ const moduleWrapper = tsserver => {
return tsserver;
}
const { isAbsolute } = require(`path`);
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(
pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
})
);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
@ -47,10 +45,7 @@ const moduleWrapper = tsserver => {
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (
locator &&
(dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))
) {
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
@ -78,55 +73,41 @@ const moduleWrapper = tsserver => {
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`:
{
str = `^zip:${str}`;
}
break;
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`:
{
str = `^/zip/${str}`;
}
break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`:
{
str = `^/zip${str}`;
}
break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`:
{
str = `^/zip/${str}`;
}
break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`:
{
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
}
break;
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`:
{
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
}
break;
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default:
{
str = `zip:${str}`;
}
break;
default: {
str = `zip:${str}`;
} break;
}
} else {
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
@ -138,30 +119,26 @@ const moduleWrapper = tsserver => {
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`:
{
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32` ? str.replace(/^.*zipfile:\//, ``) : str.replace(/^.*zipfile:/, ``);
}
break;
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`:
{
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
}
break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default:
{
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`);
}
break;
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
@ -173,8 +150,8 @@ const moduleWrapper = tsserver => {
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const { enablePluginsWithOptions: originalEnablePluginsWithOptions } = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function () {
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
@ -184,12 +161,12 @@ const moduleWrapper = tsserver => {
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const { onMessage: originalOnMessage, send: originalSend } = Session.prototype;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === "string";
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
@ -200,12 +177,10 @@ const moduleWrapper = tsserver => {
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (
process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []
).map(Number);
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
@ -220,22 +195,20 @@ const moduleWrapper = tsserver => {
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === "string" ? fromEditorPath(value) : value;
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(this, isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON));
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(
this,
JSON.parse(
JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})
)
);
},
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
@ -14,18 +14,16 @@ const moduleWrapper = tsserver => {
return tsserver;
}
const { isAbsolute } = require(`path`);
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(
pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
})
);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
@ -47,10 +45,7 @@ const moduleWrapper = tsserver => {
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (
locator &&
(dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))
) {
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
@ -78,55 +73,41 @@ const moduleWrapper = tsserver => {
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`:
{
str = `^zip:${str}`;
}
break;
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`:
{
str = `^/zip/${str}`;
}
break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`:
{
str = `^/zip${str}`;
}
break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`:
{
str = `^/zip/${str}`;
}
break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`:
{
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
}
break;
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`:
{
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
}
break;
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default:
{
str = `zip:${str}`;
}
break;
default: {
str = `zip:${str}`;
} break;
}
} else {
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
@ -138,30 +119,26 @@ const moduleWrapper = tsserver => {
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`:
{
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32` ? str.replace(/^.*zipfile:\//, ``) : str.replace(/^.*zipfile:/, ``);
}
break;
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`:
{
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
}
break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default:
{
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`);
}
break;
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
@ -173,8 +150,8 @@ const moduleWrapper = tsserver => {
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const { enablePluginsWithOptions: originalEnablePluginsWithOptions } = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function () {
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
@ -184,12 +161,12 @@ const moduleWrapper = tsserver => {
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const { onMessage: originalOnMessage, send: originalSend } = Session.prototype;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === "string";
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
@ -200,12 +177,10 @@ const moduleWrapper = tsserver => {
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (
process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []
).map(Number);
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
@ -220,22 +195,20 @@ const moduleWrapper = tsserver => {
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === "string" ? fromEditorPath(value) : value;
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(this, isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON));
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(
this,
JSON.parse(
JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})
)
);
},
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;

View File

@ -1,8 +1,8 @@
#!/usr/bin/env node
const { existsSync } = require(`fs`);
const { createRequire } = require(`module`);
const { resolve } = require(`path`);
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
@ -11,10 +11,10 @@ const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/typescript.js
// Setup the environment to be able to require typescript
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/typescript.js your application uses
module.exports = absRequire(`typescript/lib/typescript.js`);
// Defer to the real typescript your application uses
module.exports = absRequire(`typescript`);

View File

@ -2,5 +2,9 @@
"name": "typescript",
"version": "5.2.2-sdk",
"main": "./lib/typescript.js",
"type": "commonjs"
"type": "commonjs",
"bin": {
"tsc": "./bin/tsc",
"tsserver": "./bin/tsserver"
}
}

View File

@ -13,5 +13,6 @@
<body>
<div id="root"></div>
<script src="src/index.tsx" type="module"></script>
</body>
</html>

View File

@ -14,14 +14,12 @@
"@radix-ui/react-toggle": "^1.0.3",
"@react-hook/resize-observer": "^1.2.6",
"@scure/base": "^1.1.1",
"@snort/shared": "^1.0.9",
"@snort/system": "^1.1.4",
"@snort/system-react": "^1.1.4",
"@snort/shared": "^1.0.10",
"@snort/system": "^1.1.5",
"@snort/system-react": "^1.1.5",
"@snort/system-wasm": "^1.0.1",
"@snort/system-web": "^1.0.2",
"@szhsin/react-menu": "^4.0.2",
"@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0",
"@testing-library/user-event": "^13.2.1",
"@types/webscopeio__react-textarea-autocomplete": "^4.7.2",
"@void-cat/api": "^1.0.7",
"@webscopeio/react-textarea-autocomplete": "^4.9.2",
@ -32,7 +30,6 @@
"lodash": "^4.17.21",
"lodash.uniqby": "^4.7.0",
"marked": "^9.1.2",
"moment": "^2.29.4",
"qr-code-styling": "^1.6.0-rc.1",
"react": "^18.2.0",
"react-confetti": "^6.1.0",
@ -55,8 +52,8 @@
"workbox-strategies": "^7.0.0"
},
"scripts": {
"start": "webpack serve --node-env=development --mode=development",
"build": "webpack --node-env=production --mode=production",
"start": "vite",
"build": "vite build",
"deploy": "__XXX='false' && yarn build && npx wrangler pages publish --project-name nostr-live build",
"deploy:xxzap": "__XXX='true' && yarn build && npx wrangler pages publish --project-name xxzap build",
"intl-extract": "formatjs extract 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file src/lang.json --flatten true",
@ -83,40 +80,27 @@
]
},
"devDependencies": {
"@babel/core": "^7.22.11",
"@babel/plugin-syntax-import-assertions": "^7.20.0",
"@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6",
"@formatjs/cli": "^6.1.3",
"@formatjs/ts-transformer": "^3.13.3",
"@testing-library/dom": "^9.3.1",
"@types/lodash": "^4.14.195",
"@types/lodash.uniqby": "^4.7.7",
"@types/node": "^20.10.3",
"@types/react": "^18.2.21",
"@types/react-dom": "^18.2.7",
"@types/react-helmet": "^6.1.6",
"@typescript-eslint/eslint-plugin": "^6.4.1",
"@typescript-eslint/parser": "^6.4.1",
"@vitejs/plugin-react": "^4.2.0",
"@webbtc/webln-types": "^1.0.12",
"babel-loader": "^9.1.3",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"css-minimizer-webpack-plugin": "^5.0.0",
"eslint": "^8.48.0",
"eslint-webpack-plugin": "^4.0.1",
"html-webpack-plugin": "^5.5.1",
"mini-css-extract-plugin": "^2.7.5",
"eslint-plugin-formatjs": "^4.11.3",
"prettier": "^2.8.8",
"prop-types": "^15.8.1",
"source-map-loader": "^4.0.1",
"terser-webpack-plugin": "^5.3.9",
"ts-loader": "^9.4.4",
"typescript": "^5.2.2",
"webpack": "^5.88.2",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.15.1",
"workbox-webpack-plugin": "^7.0.0"
"vite": "^5.0.5",
"vite-plugin-pwa": "^0.17.2",
"vite-plugin-version-mark": "^0.0.10"
},
"packageManager": "yarn@3.6.3",
"prettier": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

View File

@ -1 +0,0 @@
[{ "id": "nsfw", "text": "NSFW" }]

View File

@ -1,14 +1,14 @@
import "./event.css";
import { type NostrLink, type NostrEvent as NostrEventType, EventKind } from "@snort/system";
import { EventKind, type NostrEvent as NostrEventType, type NostrLink } from "@snort/system";
import { Icon } from "element/icon";
import { Goal } from "element/goal";
import { Note } from "element/note";
import { EmojiPack } from "element/emoji-pack";
import { Badge } from "element/badge";
import { useEvent } from "hooks/event";
import { GOAL, EMOJI_PACK } from "const";
import { Icon } from "./icon";
import { Goal } from "./goal";
import { Note } from "./note";
import { EmojiPack } from "./emoji-pack";
import { Badge } from "./badge";
import { useEvent } from "@/hooks/event";
import { EMOJI_PACK, GOAL } from "@/const";
interface EventProps {
link: NostrLink;

View File

@ -1,6 +1,6 @@
import "./async-button.css";
import { useState } from "react";
import Spinner from "element/spinner";
import Spinner from "./spinner";
interface AsyncButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
disabled?: boolean;

View File

@ -1,6 +1,6 @@
import "./badge.css";
import type { NostrEvent } from "@snort/system";
import { findTag } from "utils";
import { findTag } from "@/utils";
export function Badge({ ev }: { ev: NostrEvent }) {
const name = findTag(ev, "name") || findTag(ev, "d");

View File

@ -1,20 +1,21 @@
import { useUserProfile, SnortContext, useEventReactions } from "@snort/system-react";
import { SnortContext, useEventReactions, useUserProfile } from "@snort/system-react";
import { EventKind, NostrLink, TaggedNostrEvent } from "@snort/system";
import React, { useRef, useState, useMemo, useContext } from "react";
import { useMediaQuery, useHover, useOnClickOutside, useIntersectionObserver } from "usehooks-ts";
import React, { useContext, useMemo, useRef, useState } from "react";
import { useHover, useIntersectionObserver, useMediaQuery, useOnClickOutside } from "usehooks-ts";
import { dedupe } from "@snort/shared";
import { EmojiPicker } from "element/emoji-picker";
import { Icon } from "element/icon";
import { Emoji as EmojiComponent } from "element/emoji";
import { EmojiPicker } from "./emoji-picker";
import { Icon } from "./icon";
import { Emoji as EmojiComponent } from "./emoji";
import { Profile } from "./profile";
import { Text } from "element/text";
import { useMute } from "element/mute-button";
import { SendZapsDialog } from "element/send-zap";
import { CollapsibleEvent } from "element/collapsible";
import { useLogin } from "hooks/login";
import { formatSats } from "number";
import type { Badge, Emoji, EmojiPack } from "types";
import { Text } from "./text";
import { useMute } from "./mute-button";
import { SendZapsDialog } from "./send-zap";
import { CollapsibleEvent } from "./collapsible";
import { useLogin } from "@/hooks/login";
import { formatSats } from "@/number";
import type { Badge, Emoji, EmojiPack } from "@/types";
function emojifyReaction(reaction: string) {
if (reaction === "+") {

View File

@ -8,10 +8,10 @@ import * as Collapsible from "@radix-ui/react-collapsible";
import type { NostrLink } from "@snort/system";
import { Mention } from "element/mention";
import { NostrEvent, EventIcon } from "element/Event";
import { ExternalLink } from "element/external-link";
import { useEvent } from "hooks/event";
import { Mention } from "./mention";
import { EventIcon, NostrEvent } from "./Event";
import { ExternalLink } from "./external-link";
import { useEvent } from "@/hooks/event";
interface MediaURLProps {
url: URL;
@ -32,7 +32,7 @@ export function MediaURL({ url, children }: MediaURLProps) {
</div>
<Dialog.Close asChild>
<button className="btn delete-button" aria-label="Close">
<FormattedMessage defaultMessage="Close" />
<FormattedMessage defaultMessage="Close" id="rbrahO" />
</button>
</Dialog.Close>
</Dialog.Content>
@ -55,7 +55,11 @@ export function CollapsibleEvent({ link }: { link: NostrLink }) {
</div>
<Collapsible.Trigger asChild>
<button className={`${open ? "btn btn-small delete-button" : "btn btn-small"}`}>
{open ? <FormattedMessage defaultMessage="Hide" /> : <FormattedMessage defaultMessage="Show" />}
{open ? (
<FormattedMessage defaultMessage="Hide" id="VA/Z1S" />
) : (
<FormattedMessage defaultMessage="Show" id="K7AkdL" />
)}
</button>
</Collapsible.Trigger>
</div>

View File

@ -19,17 +19,17 @@ export function ContentWarningOverlay() {
return (
<div className="fullscreen-exclusive age-check">
<h1>
<FormattedMessage defaultMessage="Sexually explicit material ahead!" />
<FormattedMessage defaultMessage="Sexually explicit material ahead!" id="rWBFZA" />
</h1>
<h2>
<FormattedMessage defaultMessage="Confirm your age" />
<FormattedMessage defaultMessage="Confirm your age" id="s7V+5p" />
</h2>
<div className="flex g24">
<button className="btn btn-warning" onClick={grownUp}>
<FormattedMessage defaultMessage="Yes, I am over 18" />
<FormattedMessage defaultMessage="Yes, I am over 18" id="O2Cy6m" />
</button>
<button className="btn" onClick={() => navigate("/")}>
<FormattedMessage defaultMessage="No, I am under 18" />
<FormattedMessage defaultMessage="No, I am under 18" id="KkIL3s" />
</button>
</div>
</div>

View File

@ -1,5 +1,5 @@
import "./copy.css";
import { useCopy } from "hooks/copy";
import { useCopy } from "@/hooks/copy";
import { Icon } from "./icon";
export interface CopyProps {

View File

@ -1,17 +1,17 @@
import "./emoji-pack.css";
import { type NostrEvent } from "@snort/system";
import { useLogin } from "hooks/login";
import { toEmojiPack } from "hooks/emoji";
import AsyncButton from "element/async-button";
import { findTag } from "utils";
import { USER_EMOJIS } from "const";
import { Login } from "index";
import type { EmojiPack as EmojiPackType } from "types";
import { FormattedMessage } from "react-intl";
import { useContext } from "react";
import { SnortContext } from "@snort/system-react";
import { useLogin } from "@/hooks/login";
import { toEmojiPack } from "@/hooks/emoji";
import AsyncButton from "./async-button";
import { findTag } from "@/utils";
import { USER_EMOJIS } from "@/const";
import { Login } from "@/index";
import type { EmojiPack as EmojiPackType } from "@/types";
export function EmojiPack({ ev }: { ev: NostrEvent }) {
const system = useContext(SnortContext);
const login = useLogin();
@ -49,7 +49,11 @@ export function EmojiPack({ ev }: { ev: NostrEvent }) {
<AsyncButton
className={`btn btn-small btn-primary ${isUsed ? "delete-button" : ""}`}
onClick={toggleEmojiPack}>
{isUsed ? <FormattedMessage defaultMessage="Remove" /> : <FormattedMessage defaultMessage="Add" />}
{isUsed ? (
<FormattedMessage defaultMessage="Remove" id="G/yZLu" />
) : (
<FormattedMessage defaultMessage="Add" id="2/2yg+" />
)}
</AsyncButton>
)}
</div>

View File

@ -1,7 +1,7 @@
import data, { Emoji } from "@emoji-mart/data";
import Picker from "@emoji-mart/react";
import { RefObject } from "react";
import { EmojiPack } from "types";
import { EmojiPack } from "@/types";
interface EmojiPickerProps {
topOffset: number;

View File

@ -1,6 +1,6 @@
import "./emoji.css";
import { useMemo } from "react";
import { EmojiTag } from "types";
import { EmojiTag } from "@/types";
export type EmojiProps = {
name: string;

View File

@ -1,5 +1,5 @@
import type { ReactNode } from "react";
import { Icon } from "element/icon";
import { Icon } from "./icon";
interface ExternalLinkProps {
href: string;

View File

@ -79,15 +79,15 @@ export function FileUploader({ defaultImage, onClear, onFileUpload }: FileUpload
<label className="file-uploader">
<input type="file" onChange={onFileChange} />
{isUploading ? (
<FormattedMessage defaultMessage="Uploading..." />
<FormattedMessage defaultMessage="Uploading..." id="JEsxDw" />
) : (
<FormattedMessage defaultMessage="Add File" />
<FormattedMessage defaultMessage="Add File" id="fc2iho" />
)}
</label>
<div className="file-uploader-preview">
{img?.length > 0 && (
<button className="btn btn-primary clear-button" onClick={clearImage}>
<FormattedMessage defaultMessage="Clear" />
<FormattedMessage defaultMessage="Clear" id="/GCoTA" />
</button>
)}
{img && <img className="image-preview" src={img} />}

View File

@ -1,12 +1,12 @@
import { EventKind } from "@snort/system";
import { useLogin } from "hooks/login";
import AsyncButton from "element/async-button";
import { Login } from "index";
import { FormattedMessage } from "react-intl";
import { useContext } from "react";
import { SnortContext } from "@snort/system-react";
import { useLogin } from "@/hooks/login";
import AsyncButton from "./async-button";
import { Login } from "@/index";
export function LoggedInFollowButton({ tag, value }: { tag: "p" | "t"; value: string }) {
const system = useContext(SnortContext);
const login = useLogin();
@ -56,7 +56,11 @@ export function LoggedInFollowButton({ tag, value }: { tag: "p" | "t"; value: st
type="button"
className="btn btn-primary"
onClick={isFollowing ? unfollow : follow}>
{isFollowing ? <FormattedMessage defaultMessage="Unfollow" /> : <FormattedMessage defaultMessage="Follow" />}
{isFollowing ? (
<FormattedMessage defaultMessage="Unfollow" id="izWS4J" />
) : (
<FormattedMessage defaultMessage="Follow" id="ieGrWo" />
)}
</AsyncButton>
);
}

View File

@ -2,18 +2,18 @@ import "./goal.css";
import { useMemo } from "react";
import * as Progress from "@radix-ui/react-progress";
import Confetti from "react-confetti";
import { FormattedMessage } from "react-intl";
import { NostrLink, type NostrEvent } from "@snort/system";
import { type NostrEvent, NostrLink } from "@snort/system";
import { useUserProfile } from "@snort/system-react";
import { findTag } from "utils";
import { formatSats } from "number";
import usePreviousValue from "hooks/usePreviousValue";
import { SendZapsDialog } from "element/send-zap";
import { getName } from "element/profile";
import { findTag } from "@/utils";
import { formatSats } from "@/number";
import usePreviousValue from "@/hooks/usePreviousValue";
import { SendZapsDialog } from "./send-zap";
import { getName } from "./profile";
import { Icon } from "./icon";
import { FormattedMessage } from "react-intl";
import { useZaps } from "hooks/zaps";
import { useZaps } from "@/hooks/zaps";
export function Goal({ ev }: { ev: NostrEvent }) {
const profile = useUserProfile(ev.pubkey);
@ -48,7 +48,7 @@ export function Goal({ ev }: { ev: NostrEvent }) {
{!isFinished && <span className="amount so-far">{formatSats(soFar)}</span>}
</Progress.Indicator>
<span className="amount target">
<FormattedMessage defaultMessage="Goal: {amount}" values={{ amount: formatSats(goalAmount) }} />
<FormattedMessage defaultMessage="Goal: {amount}" id="QceMQZ" values={{ amount: formatSats(goalAmount) }} />
</span>
</Progress.Root>
<div className="zap-circle">

View File

@ -1,6 +1,6 @@
import type { ReactNode } from "react";
import { NostrLink } from "element/nostr-link";
import { MediaURL } from "element/collapsible";
import { NostrLink } from "./nostr-link";
import { MediaURL } from "./collapsible";
const FileExtensionRegex = /\.([\w]+)$/i;

View File

@ -1,29 +1,29 @@
import "./live-chat.css";
import { FormattedMessage } from "react-intl";
import { EventKind, NostrLink, ParsedZap, NostrEvent } from "@snort/system";
import { EventKind, NostrEvent, NostrLink, ParsedZap } from "@snort/system";
import { useEventReactions } from "@snort/system-react";
import { unixNow } from "@snort/shared";
import { useMemo } from "react";
import uniqBy from "lodash.uniqby";
import { Icon } from "element/icon";
import Spinner from "element/spinner";
import { Text } from "element/text";
import { Profile } from "element/profile";
import { ChatMessage } from "element/chat-message";
import { Goal } from "element/goal";
import { Badge } from "element/badge";
import { WriteMessage } from "element/write-message";
import useEmoji, { packId } from "hooks/emoji";
import { useLiveChatFeed } from "hooks/live-chat";
import { useMutedPubkeys } from "hooks/lists";
import { useBadges } from "hooks/badges";
import { useLogin } from "hooks/login";
import { useAddress } from "hooks/event";
import { formatSats } from "number";
import { WEEK, LIVE_STREAM_CHAT } from "const";
import { findTag, getTagValues, getHost } from "utils";
import { TopZappers } from "element/top-zappers";
import { Icon } from "./icon";
import Spinner from "./spinner";
import { Text } from "./text";
import { Profile } from "./profile";
import { ChatMessage } from "./chat-message";
import { Goal } from "./goal";
import { Badge } from "./badge";
import { WriteMessage } from "./write-message";
import useEmoji, { packId } from "@/hooks/emoji";
import { useLiveChatFeed } from "@/hooks/live-chat";
import { useMutedPubkeys } from "@/hooks/lists";
import { useBadges } from "@/hooks/badges";
import { useLogin } from "@/hooks/login";
import { useAddress } from "@/hooks/event";
import { formatSats } from "@/number";
import { LIVE_STREAM_CHAT, WEEK } from "@/const";
import { findTag, getHost, getTagValues } from "@/utils";
import { TopZappers } from "./top-zappers";
export interface LiveChatOptions {
canWrite?: boolean;
@ -95,7 +95,7 @@ export function LiveChat({
{(options?.showHeader ?? true) && (
<div className="header">
<h2 className="title">
<FormattedMessage defaultMessage="Stream Chat" />
<FormattedMessage defaultMessage="Stream Chat" id="BGxpTN" />
</h2>
<Icon
name="link"
@ -108,7 +108,7 @@ export function LiveChat({
{reactions.zaps.length > 0 && (
<div className="top-zappers">
<h3>
<FormattedMessage defaultMessage="Top zappers" />
<FormattedMessage defaultMessage="Top zappers" id="wzWWzV" />
</h3>
<div className="top-zappers-container">
<TopZappers zaps={reactions.zaps} />
@ -151,7 +151,7 @@ export function LiveChat({
<WriteMessage emojiPacks={allEmojiPacks} link={link} />
) : (