Setup
This commit is contained in:
commit
f11e93a4db
10
.editorconfig
Normal file
10
.editorconfig
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.{js,json,yml}]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
20
.eslintrc.cjs
Normal file
20
.eslintrc.cjs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||||
|
parser: "@typescript-eslint/parser",
|
||||||
|
plugins: ["@typescript-eslint"],
|
||||||
|
root: true,
|
||||||
|
ignorePatterns: ["build/", "*.test.ts", "*.js"],
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
worker: true,
|
||||||
|
commonjs: true,
|
||||||
|
node: false,
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"@typescript-eslint/no-non-null-assertion": "error",
|
||||||
|
"require-await": "error",
|
||||||
|
"eqeqeq": "error",
|
||||||
|
"object-shorthand": "warn",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
/.yarn/** linguist-vendored
|
||||||
|
/.yarn/releases/* binary
|
||||||
|
/.yarn/plugins/**/* binary
|
||||||
|
/.pnp.* binary linguist-generated
|
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/sdks
|
||||||
|
!.yarn/versions
|
||||||
|
|
||||||
|
# Swap the comments on the following lines if you don't wish to use zero-installs
|
||||||
|
# Documentation here: https://yarnpkg.com/features/zero-installs
|
||||||
|
#!.yarn/cache
|
||||||
|
.pnp.*
|
7
.vscode/extensions.json
vendored
Normal file
7
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"arcanis.vscode-zipfs",
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"esbenp.prettier-vscode"
|
||||||
|
]
|
||||||
|
}
|
10
.vscode/settings.json
vendored
Normal file
10
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"search.exclude": {
|
||||||
|
"**/.yarn": true,
|
||||||
|
"**/.pnp.*": true
|
||||||
|
},
|
||||||
|
"eslint.nodePath": ".yarn/sdks",
|
||||||
|
"prettier.prettierPath": ".yarn/sdks/prettier/index.js",
|
||||||
|
"typescript.tsdk": ".yarn/sdks/typescript/lib",
|
||||||
|
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||||
|
}
|
BIN
.yarn/releases/yarn-3.6.1.cjs
vendored
Executable file
BIN
.yarn/releases/yarn-3.6.1.cjs
vendored
Executable file
Binary file not shown.
20
.yarn/sdks/eslint/bin/eslint.js
vendored
Executable file
20
.yarn/sdks/eslint/bin/eslint.js
vendored
Executable 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/bin/eslint.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real eslint/bin/eslint.js your application uses
|
||||||
|
module.exports = absRequire(`eslint/bin/eslint.js`);
|
20
.yarn/sdks/eslint/lib/api.js
vendored
Normal file
20
.yarn/sdks/eslint/lib/api.js
vendored
Normal 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
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real eslint your application uses
|
||||||
|
module.exports = absRequire(`eslint`);
|
6
.yarn/sdks/eslint/package.json
vendored
Normal file
6
.yarn/sdks/eslint/package.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "eslint",
|
||||||
|
"version": "8.46.0-sdk",
|
||||||
|
"main": "./lib/api.js",
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
5
.yarn/sdks/integrations.yml
vendored
Normal file
5
.yarn/sdks/integrations.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# This file is automatically generated by @yarnpkg/sdks.
|
||||||
|
# Manual changes might be lost!
|
||||||
|
|
||||||
|
integrations:
|
||||||
|
- vscode
|
20
.yarn/sdks/prettier/index.js
vendored
Executable file
20
.yarn/sdks/prettier/index.js
vendored
Executable 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
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real prettier your application uses
|
||||||
|
module.exports = absRequire(`prettier`);
|
6
.yarn/sdks/prettier/package.json
vendored
Normal file
6
.yarn/sdks/prettier/package.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "prettier",
|
||||||
|
"version": "3.0.1-sdk",
|
||||||
|
"main": "./index.js",
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
20
.yarn/sdks/typescript/bin/tsc
vendored
Executable file
20
.yarn/sdks/typescript/bin/tsc
vendored
Executable 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 typescript/bin/tsc
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/bin/tsc your application uses
|
||||||
|
module.exports = absRequire(`typescript/bin/tsc`);
|
20
.yarn/sdks/typescript/bin/tsserver
vendored
Executable file
20
.yarn/sdks/typescript/bin/tsserver
vendored
Executable 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 typescript/bin/tsserver
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/bin/tsserver your application uses
|
||||||
|
module.exports = absRequire(`typescript/bin/tsserver`);
|
20
.yarn/sdks/typescript/lib/tsc.js
vendored
Normal file
20
.yarn/sdks/typescript/lib/tsc.js
vendored
Normal 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 typescript/lib/tsc.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/tsc.js your application uses
|
||||||
|
module.exports = absRequire(`typescript/lib/tsc.js`);
|
225
.yarn/sdks/typescript/lib/tsserver.js
vendored
Normal file
225
.yarn/sdks/typescript/lib/tsserver.js
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
#!/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);
|
||||||
|
|
||||||
|
const moduleWrapper = tsserver => {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
return tsserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
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}`;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||||
|
// doesn't understand. This layer makes sure to remove the protocol
|
||||||
|
// before forwarding it to TS, and to add it back on all returned paths.
|
||||||
|
|
||||||
|
function toEditorPath(str) {
|
||||||
|
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||||
|
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||||
|
// We also take the opportunity to turn virtual paths into physical ones;
|
||||||
|
// this makes it much easier to work with workspaces that list peer
|
||||||
|
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||||
|
// file instances instead of the real ones.
|
||||||
|
//
|
||||||
|
// We only do this to modules owned by the the dependency tree roots.
|
||||||
|
// This avoids breaking the resolution when jumping inside a vendor
|
||||||
|
// with peer dep (otherwise jumping into react-dom would show resolution
|
||||||
|
// errors on react).
|
||||||
|
//
|
||||||
|
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))) {
|
||||||
|
str = resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = normalize(str);
|
||||||
|
|
||||||
|
if (str.match(/\.zip\//)) {
|
||||||
|
switch (hostInfo) {
|
||||||
|
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
|
||||||
|
// VSCode only adds it automatically for supported schemes,
|
||||||
|
// so we have to do it manually for the `zip` scheme.
|
||||||
|
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
|
||||||
|
//
|
||||||
|
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||||
|
//
|
||||||
|
// 2021-10-08: VSCode changed the format in 1.61.
|
||||||
|
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-04-06: VSCode changed the format in 1.66.
|
||||||
|
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-05-06: VSCode changed the format in 1.68
|
||||||
|
// 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.66`: {
|
||||||
|
str = `^/zip/${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode <1.68`: {
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
str = `zip:${str}`;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 `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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force enable 'allowLocalPluginLoads'
|
||||||
|
// TypeScript tries to resolve plugins using a path relative to itself
|
||||||
|
// which doesn't work when using the global cache
|
||||||
|
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
|
||||||
|
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
|
||||||
|
// 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() {
|
||||||
|
this.projectService.allowLocalPluginLoads = true;
|
||||||
|
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// And here is the point where we hijack the VSCode <-> TS communications
|
||||||
|
// by adding ourselves in the middle. We locate everything that looks
|
||||||
|
// like an absolute path of ours and normalize it.
|
||||||
|
|
||||||
|
const Session = tsserver.server.Session;
|
||||||
|
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 parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||||
|
|
||||||
|
if (
|
||||||
|
parsedMessage != null &&
|
||||||
|
typeof parsedMessage === `object` &&
|
||||||
|
parsedMessage.arguments &&
|
||||||
|
typeof parsedMessage.arguments.hostInfo === `string`
|
||||||
|
) {
|
||||||
|
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)
|
||||||
|
|
||||||
|
if (major === 1) {
|
||||||
|
if (minor < 61) {
|
||||||
|
hostInfo += ` <1.61`;
|
||||||
|
} else if (minor < 66) {
|
||||||
|
hostInfo += ` <1.66`;
|
||||||
|
} else if (minor < 68) {
|
||||||
|
hostInfo += ` <1.68`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||||
|
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||||
|
});
|
||||||
|
|
||||||
|
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 tsserver;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/lib/tsserver.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/tsserver.js your application uses
|
||||||
|
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));
|
225
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
Normal file
225
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
#!/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);
|
||||||
|
|
||||||
|
const moduleWrapper = tsserver => {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
return tsserver;
|
||||||
|
}
|
||||||
|
|
||||||
|
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}`;
|
||||||
|
}));
|
||||||
|
|
||||||
|
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||||
|
// doesn't understand. This layer makes sure to remove the protocol
|
||||||
|
// before forwarding it to TS, and to add it back on all returned paths.
|
||||||
|
|
||||||
|
function toEditorPath(str) {
|
||||||
|
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||||
|
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||||
|
// We also take the opportunity to turn virtual paths into physical ones;
|
||||||
|
// this makes it much easier to work with workspaces that list peer
|
||||||
|
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||||
|
// file instances instead of the real ones.
|
||||||
|
//
|
||||||
|
// We only do this to modules owned by the the dependency tree roots.
|
||||||
|
// This avoids breaking the resolution when jumping inside a vendor
|
||||||
|
// with peer dep (otherwise jumping into react-dom would show resolution
|
||||||
|
// errors on react).
|
||||||
|
//
|
||||||
|
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))) {
|
||||||
|
str = resolved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = normalize(str);
|
||||||
|
|
||||||
|
if (str.match(/\.zip\//)) {
|
||||||
|
switch (hostInfo) {
|
||||||
|
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
|
||||||
|
// VSCode only adds it automatically for supported schemes,
|
||||||
|
// so we have to do it manually for the `zip` scheme.
|
||||||
|
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
|
||||||
|
//
|
||||||
|
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
|
||||||
|
//
|
||||||
|
// 2021-10-08: VSCode changed the format in 1.61.
|
||||||
|
// Before | ^zip:/c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-04-06: VSCode changed the format in 1.66.
|
||||||
|
// Before | ^/zip//c:/foo/bar.zip/package.json
|
||||||
|
// After | ^/zip/c:/foo/bar.zip/package.json
|
||||||
|
//
|
||||||
|
// 2022-05-06: VSCode changed the format in 1.68
|
||||||
|
// 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.66`: {
|
||||||
|
str = `^/zip/${str}`;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case `vscode <1.68`: {
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
default: {
|
||||||
|
str = `zip:${str}`;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 `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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force enable 'allowLocalPluginLoads'
|
||||||
|
// TypeScript tries to resolve plugins using a path relative to itself
|
||||||
|
// which doesn't work when using the global cache
|
||||||
|
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
|
||||||
|
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
|
||||||
|
// 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() {
|
||||||
|
this.projectService.allowLocalPluginLoads = true;
|
||||||
|
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||||
|
};
|
||||||
|
|
||||||
|
// And here is the point where we hijack the VSCode <-> TS communications
|
||||||
|
// by adding ourselves in the middle. We locate everything that looks
|
||||||
|
// like an absolute path of ours and normalize it.
|
||||||
|
|
||||||
|
const Session = tsserver.server.Session;
|
||||||
|
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 parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||||
|
|
||||||
|
if (
|
||||||
|
parsedMessage != null &&
|
||||||
|
typeof parsedMessage === `object` &&
|
||||||
|
parsedMessage.arguments &&
|
||||||
|
typeof parsedMessage.arguments.hostInfo === `string`
|
||||||
|
) {
|
||||||
|
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)
|
||||||
|
|
||||||
|
if (major === 1) {
|
||||||
|
if (minor < 61) {
|
||||||
|
hostInfo += ` <1.61`;
|
||||||
|
} else if (minor < 66) {
|
||||||
|
hostInfo += ` <1.66`;
|
||||||
|
} else if (minor < 68) {
|
||||||
|
hostInfo += ` <1.68`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||||
|
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||||
|
});
|
||||||
|
|
||||||
|
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 tsserver;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (existsSync(absPnpApiPath)) {
|
||||||
|
if (!process.versions.pnp) {
|
||||||
|
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
|
||||||
|
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));
|
20
.yarn/sdks/typescript/lib/typescript.js
vendored
Normal file
20
.yarn/sdks/typescript/lib/typescript.js
vendored
Normal 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 typescript/lib/typescript.js
|
||||||
|
require(absPnpApiPath).setup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer to the real typescript/lib/typescript.js your application uses
|
||||||
|
module.exports = absRequire(`typescript/lib/typescript.js`);
|
6
.yarn/sdks/typescript/package.json
vendored
Normal file
6
.yarn/sdks/typescript/package.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "typescript",
|
||||||
|
"version": "5.1.6-sdk",
|
||||||
|
"main": "./lib/typescript.js",
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
1
.yarnrc.yml
Normal file
1
.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
yarnPath: .yarn/releases/yarn-3.6.1.cjs
|
1
node_modules/.cache/eslint-webpack-plugin/.eslintcache
generated
vendored
Normal file
1
node_modules/.cache/eslint-webpack-plugin/.eslintcache
generated
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{"/Users/kieran/Documents/GitHub/zap_stream_admin/src/index.tsx":"1","/Users/kieran/Documents/GitHub/zap_stream_admin/src/layout.tsx":"2","/Users/kieran/Documents/GitHub/zap_stream_admin/src/pages/root.tsx":"3"},{"size":697,"mtime":1691422030506,"results":"4","hashOfConfig":"5"},{"size":6217,"mtime":1691422351490,"results":"6","hashOfConfig":"5"},{"size":52,"mtime":1691422005081,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","suppressedMessages":"10","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"11"},"sj259k",{"filePath":"12","messages":"13","suppressedMessages":"14","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"15","messages":"16","suppressedMessages":"17","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"11"},"/Users/kieran/Documents/GitHub/zap_stream_admin/src/index.tsx",[],[],[],"/Users/kieran/Documents/GitHub/zap_stream_admin/src/layout.tsx",[],[],"/Users/kieran/Documents/GitHub/zap_stream_admin/src/pages/root.tsx",[],[]]
|
52
package.json
Normal file
52
package.json
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{
|
||||||
|
"name": "zap_stream_admin",
|
||||||
|
"packageManager": "yarn@3.6.1",
|
||||||
|
"scripts": {
|
||||||
|
"start": "webpack serve"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router-dom": "^6.14.2"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.22.9",
|
||||||
|
"@babel/preset-env": "^7.22.9",
|
||||||
|
"@babel/preset-react": "^7.22.5",
|
||||||
|
"@babel/runtime": "^7.22.6",
|
||||||
|
"@types/react": "^18.2.18",
|
||||||
|
"@types/react-dom": "^18.2.7",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.2.1",
|
||||||
|
"@typescript-eslint/parser": "^6.2.1",
|
||||||
|
"autoprefixer": "^10.4.14",
|
||||||
|
"babel-loader": "^9.1.3",
|
||||||
|
"babel-plugin-formatjs": "^10.5.3",
|
||||||
|
"copy-webpack-plugin": "^11.0.0",
|
||||||
|
"css-loader": "^6.8.1",
|
||||||
|
"css-minimizer-webpack-plugin": "^5.0.1",
|
||||||
|
"eslint": "^8.46.0",
|
||||||
|
"eslint-webpack-plugin": "^4.0.1",
|
||||||
|
"html-webpack-plugin": "^5.5.3",
|
||||||
|
"mini-css-extract-plugin": "^2.7.6",
|
||||||
|
"postcss": "^8.4.27",
|
||||||
|
"postcss-import": "^15.1.0",
|
||||||
|
"postcss-loader": "^7.3.3",
|
||||||
|
"prettier": "^3.0.1",
|
||||||
|
"source-map-loader": "^4.0.1",
|
||||||
|
"tailwindcss": "^3.3.3",
|
||||||
|
"terser-webpack-plugin": "^5.3.9",
|
||||||
|
"ts-loader": "^9.4.4",
|
||||||
|
"typescript": "^5.1.6",
|
||||||
|
"webpack": "^5.88.2",
|
||||||
|
"webpack-cli": "^5.1.4",
|
||||||
|
"webpack-dev-server": "^4.15.1"
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">1%"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 2 versions"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
10
public/index.html
Normal file
10
public/index.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
3
src/index.css
Normal file
3
src/index.css
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
30
src/index.tsx
Normal file
30
src/index.tsx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import "./index.css";
|
||||||
|
import React from "react";
|
||||||
|
import ReactDOM from "react-dom/client";
|
||||||
|
import { RouteObject, RouterProvider, createBrowserRouter } from "react-router-dom";
|
||||||
|
|
||||||
|
import { Layout } from "layout";
|
||||||
|
import { RootPage } from "pages/root";
|
||||||
|
|
||||||
|
const Routes = [
|
||||||
|
{
|
||||||
|
element: <Layout />,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
element: <RootPage />
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
] as Array<RouteObject>;
|
||||||
|
|
||||||
|
const Router = createBrowserRouter(Routes);
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(
|
||||||
|
document.getElementById("root") as HTMLDivElement
|
||||||
|
);
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<RouterProvider router={Router} />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
69
src/layout.tsx
Normal file
69
src/layout.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
export function Layout() {
|
||||||
|
return <>
|
||||||
|
<nav className="bg-gray-800">
|
||||||
|
<div className="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
|
||||||
|
<div className="relative flex h-16 items-center justify-between">
|
||||||
|
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
|
||||||
|
<button type="button" className="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white" aria-controls="mobile-menu" aria-expanded="false">
|
||||||
|
<span className="absolute -inset-0.5"></span>
|
||||||
|
<span className="sr-only">Open main menu</span>
|
||||||
|
<svg className="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
|
||||||
|
</svg>
|
||||||
|
<svg className="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
|
||||||
|
<div className="flex flex-shrink-0 items-center">
|
||||||
|
<img className="h-8 w-auto" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company" />
|
||||||
|
</div>
|
||||||
|
<div className="hidden sm:ml-6 sm:block">
|
||||||
|
<div className="flex space-x-4">
|
||||||
|
<a href="#" className="bg-gray-900 text-white rounded-md px-3 py-2 text-sm font-medium" aria-current="page">Dashboard</a>
|
||||||
|
<a href="#" className="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Team</a>
|
||||||
|
<a href="#" className="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Projects</a>
|
||||||
|
<a href="#" className="text-gray-300 hover:bg-gray-700 hover:text-white rounded-md px-3 py-2 text-sm font-medium">Calendar</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
|
||||||
|
<button type="button" className="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
|
||||||
|
<span className="absolute -inset-1.5"></span>
|
||||||
|
<span className="sr-only">View notifications</span>
|
||||||
|
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="relative ml-3">
|
||||||
|
<div>
|
||||||
|
<button type="button" className="relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800" id="user-menu-button" aria-expanded="false" aria-haspopup="true">
|
||||||
|
<span className="absolute -inset-1.5"></span>
|
||||||
|
<span className="sr-only">Open user menu</span>
|
||||||
|
<img className="h-8 w-8 rounded-full" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt="" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu" aria-orientation="vertical" aria-labelledby="user-menu-button" tabIndex={-1}>
|
||||||
|
<a href="#" className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-0">Your Profile</a>
|
||||||
|
<a href="#" className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-1">Settings</a>
|
||||||
|
<a href="#" className="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabIndex={-1} id="user-menu-item-2">Sign out</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="sm:hidden" id="mobile-menu">
|
||||||
|
<div className="space-y-1 px-2 pb-3 pt-2">
|
||||||
|
<a href="#" className="bg-gray-900 text-white block rounded-md px-3 py-2 text-base font-medium" aria-current="page">Dashboard</a>
|
||||||
|
<a href="#" className="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Team</a>
|
||||||
|
<a href="#" className="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Projects</a>
|
||||||
|
<a href="#" className="text-gray-300 hover:bg-gray-700 hover:text-white block rounded-md px-3 py-2 text-base font-medium">Calendar</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
</>
|
||||||
|
}
|
4
src/pages/root.tsx
Normal file
4
src/pages/root.tsx
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export function RootPage() {
|
||||||
|
return <>
|
||||||
|
</>
|
||||||
|
}
|
11
tailwind.config.js
Normal file
11
tailwind.config.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
"./src/**/*.{js,jsx,ts,tsx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
}
|
||||||
|
|
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src",
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "es2020",
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"sourceMap": true
|
||||||
|
}
|
||||||
|
}
|
154
webpack.config.js
Normal file
154
webpack.config.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
// Generated using webpack-cli https://github.com/webpack/webpack-cli
|
||||||
|
|
||||||
|
const path = require("path");
|
||||||
|
const webpack = require("webpack");
|
||||||
|
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||||
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
|
const ESLintPlugin = require("eslint-webpack-plugin");
|
||||||
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||||
|
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
|
||||||
|
|
||||||
|
const isProduction = process.env.NODE_ENV == "production";
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
entry: {
|
||||||
|
main: "./src/index.tsx",
|
||||||
|
},
|
||||||
|
target: "browserslist",
|
||||||
|
mode: isProduction ? "production" : "development",
|
||||||
|
devtool: isProduction ? "source-map" : "cheap-module-source-map",
|
||||||
|
output: {
|
||||||
|
publicPath: "/",
|
||||||
|
path: path.resolve(__dirname, "build"),
|
||||||
|
filename: ({ runtime }) => {
|
||||||
|
if (runtime === "sw") {
|
||||||
|
return "[name].js";
|
||||||
|
}
|
||||||
|
return isProduction ? "[name].[chunkhash].js" : "[name].js";
|
||||||
|
},
|
||||||
|
clean: isProduction,
|
||||||
|
},
|
||||||
|
devServer: {
|
||||||
|
open: true,
|
||||||
|
host: "localhost",
|
||||||
|
historyApiFallback: true,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
template: "public/index.html"
|
||||||
|
}),
|
||||||
|
new ESLintPlugin({
|
||||||
|
extensions: ["js", "mjs", "jsx", "ts", "tsx"],
|
||||||
|
eslintPath: require.resolve("eslint"),
|
||||||
|
failOnError: !isProduction,
|
||||||
|
cache: true,
|
||||||
|
}),
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: isProduction ? "[name].[chunkhash].css" : "[name].css",
|
||||||
|
}),
|
||||||
|
new webpack.IgnorePlugin({
|
||||||
|
resourceRegExp: /^\.\/locale$/,
|
||||||
|
contextRegExp: /moment$/,
|
||||||
|
}),
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
__XXX: process.env["__XXX"] || JSON.stringify(false),
|
||||||
|
__XXX_HOST: JSON.stringify("https://xxzap.com")
|
||||||
|
})
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
enforce: "pre",
|
||||||
|
exclude: /@babel(?:\/|\\{1,2})runtime/,
|
||||||
|
test: /\.(js|mjs|jsx|ts|tsx|css)$/,
|
||||||
|
loader: require.resolve("source-map-loader"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/i,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: require.resolve("babel-loader"),
|
||||||
|
options: {
|
||||||
|
babelrc: false,
|
||||||
|
configFile: false,
|
||||||
|
presets: [
|
||||||
|
["@babel/preset-env", {
|
||||||
|
targets: "defaults"
|
||||||
|
}],
|
||||||
|
["@babel/preset-react", { runtime: "automatic" }],
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
"formatjs",
|
||||||
|
{
|
||||||
|
idInterpolationPattern: "[sha512:contenthash:base64:6]",
|
||||||
|
ast: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
require.resolve("ts-loader")
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.css$/i,
|
||||||
|
use: [
|
||||||
|
MiniCssExtractPlugin.loader,
|
||||||
|
require.resolve("css-loader"),
|
||||||
|
{
|
||||||
|
loader: require.resolve("postcss-loader"),
|
||||||
|
options: {
|
||||||
|
postcssOptions: {
|
||||||
|
plugins: [
|
||||||
|
[
|
||||||
|
require("tailwindcss"),
|
||||||
|
require('autoprefixer'),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif|webp)$/i,
|
||||||
|
type: "asset",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
chunkIds: "deterministic",
|
||||||
|
minimize: isProduction,
|
||||||
|
minimizer: [
|
||||||
|
new TerserPlugin({
|
||||||
|
terserOptions: {
|
||||||
|
parse: {
|
||||||
|
ecma: 8,
|
||||||
|
},
|
||||||
|
compress: {
|
||||||
|
ecma: 5,
|
||||||
|
warnings: false,
|
||||||
|
comparisons: false,
|
||||||
|
inline: 2,
|
||||||
|
},
|
||||||
|
mangle: {
|
||||||
|
safari10: true,
|
||||||
|
},
|
||||||
|
keep_classnames: isProduction,
|
||||||
|
keep_fnames: isProduction,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
new CssMinimizerPlugin(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
aliasFields: ["browser"],
|
||||||
|
extensions: ["...", ".tsx", ".ts", ".jsx", ".js"],
|
||||||
|
modules: ["...", __dirname, path.resolve(__dirname, "src")],
|
||||||
|
fallback: { "crypto": false }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = () => config;
|
Loading…
Reference in New Issue
Block a user