@tanstack/router-vite-plugin 1.26.6 → 1.26.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/eliminateUnreferencedIdentifiers.cjs +14 -13
- package/dist/cjs/eliminateUnreferencedIdentifiers.cjs.map +1 -1
- package/dist/esm/eliminateUnreferencedIdentifiers.js +14 -13
- package/dist/esm/eliminateUnreferencedIdentifiers.js.map +1 -1
- package/package.json +2 -2
- package/src/eliminateUnreferencedIdentifiers.ts +21 -13
- package/src/tests/index.test.ts +0 -60
- package/src/tests/shared/imported.tsx +0 -11
- package/src/tests/snapshots/function-declaration.tsx +0 -10
- package/src/tests/snapshots/function-declaration?split.tsx +0 -29
- package/src/tests/snapshots/imported.tsx +0 -10
- package/src/tests/snapshots/imported?split.tsx +0 -5
- package/src/tests/snapshots/inline.tsx +0 -8
- package/src/tests/snapshots/inline?split.tsx +0 -18
- package/src/tests/snapshots/random-number.tsx +0 -11
- package/src/tests/snapshots/random-number?split.tsx +0 -27
- package/src/tests/test-files/function-declaration.tsx +0 -39
- package/src/tests/test-files/imported.tsx +0 -8
- package/src/tests/test-files/inline.tsx +0 -25
- package/src/tests/test-files/random-number.tsx +0 -83
|
@@ -82,25 +82,26 @@ const eliminateUnreferencedIdentifiers = (programPath, refs) => {
|
|
|
82
82
|
}
|
|
83
83
|
} else if (path.node.id.type === "ArrayPattern") {
|
|
84
84
|
const pattern = path.get("id");
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if ((
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
85
|
+
let hasRemoved = false;
|
|
86
|
+
pattern.get("elements").forEach((element, index) => {
|
|
87
|
+
let identifierPath;
|
|
88
|
+
if (t__namespace.isIdentifier(element.node)) {
|
|
89
|
+
identifierPath = element;
|
|
90
|
+
} else if (t__namespace.isRestElement(element.node)) {
|
|
91
|
+
identifierPath = element.get(
|
|
92
|
+
"argument"
|
|
93
|
+
);
|
|
94
94
|
} else {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
-
if (shouldBeRemoved(
|
|
98
|
-
|
|
99
|
-
|
|
97
|
+
if (shouldBeRemoved(identifierPath)) {
|
|
98
|
+
hasRemoved = true;
|
|
99
|
+
pattern.node.elements[index] = null;
|
|
100
100
|
}
|
|
101
101
|
});
|
|
102
|
-
if (
|
|
102
|
+
if (hasRemoved && pattern.node.elements.every((element) => element === null)) {
|
|
103
103
|
path.remove();
|
|
104
|
+
++referencesRemovedInThisPass;
|
|
104
105
|
}
|
|
105
106
|
}
|
|
106
107
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eliminateUnreferencedIdentifiers.cjs","sources":["../../src/eliminateUnreferencedIdentifiers.ts"],"sourcesContent":["// Copied from https://github.com/pcattori/vite-env-only/blob/main/src/dce.ts\n// Adapted with some minor changes for the purpose of this project\n\nimport * as t from '@babel/types'\nimport type { types as BabelTypes } from '@babel/core'\nimport type { NodePath } from '@babel/traverse'\n\ntype IdentifierPath = NodePath<BabelTypes.Identifier>\n\n// export function findReferencedIdentifiers(\n// programPath: NodePath<BabelTypes.Program>,\n// ): Set<IdentifierPath> {\n// const refs = new Set<IdentifierPath>()\n\n// function markFunction(\n// path: NodePath<\n// | BabelTypes.FunctionDeclaration\n// | BabelTypes.FunctionExpression\n// | BabelTypes.ArrowFunctionExpression\n// >,\n// ) {\n// const ident = getIdentifier(path)\n// if (ident?.node && isIdentifierReferenced(ident)) {\n// refs.add(ident)\n// }\n// }\n\n// function markImport(\n// path: NodePath<\n// | BabelTypes.ImportSpecifier\n// | BabelTypes.ImportDefaultSpecifier\n// | BabelTypes.ImportNamespaceSpecifier\n// >,\n// ) {\n// const local = path.get('local')\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// }\n\n// programPath.traverse({\n// VariableDeclarator(path) {\n// if (path.node.id.type === 'Identifier') {\n// const local = path.get('id') as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// } else if (path.node.id.type === 'ObjectPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n// const properties = pattern.get('properties')\n// properties.forEach((p) => {\n// const local = p.get(\n// p.node.type === 'ObjectProperty'\n// ? 'value'\n// : p.node.type === 'RestElement'\n// ? 'argument'\n// : (function () {\n// throw new Error('invariant')\n// })(),\n// ) as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// } else if (path.node.id.type === 'ArrayPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n// const elements = pattern.get('elements')\n// elements.forEach((e) => {\n// let local: NodePath<BabelTypes.Identifier>\n// if (e.node?.type === 'Identifier') {\n// local = e as NodePath<BabelTypes.Identifier>\n// } else if (e.node?.type === 'RestElement') {\n// local = e.get('argument') as NodePath<BabelTypes.Identifier>\n// } else {\n// return\n// }\n\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// }\n// },\n\n// FunctionDeclaration: markFunction,\n// FunctionExpression: markFunction,\n// ArrowFunctionExpression: markFunction,\n// ImportSpecifier: markImport,\n// ImportDefaultSpecifier: markImport,\n// ImportNamespaceSpecifier: markImport,\n// })\n// return refs\n// }\n\n/**\n * @param refs - If provided, only these identifiers will be considered for removal.\n */\nexport const eliminateUnreferencedIdentifiers = (\n programPath: NodePath<BabelTypes.Program>,\n refs?: Set<IdentifierPath>,\n) => {\n let referencesRemovedInThisPass: number\n\n const shouldBeRemoved = (ident: IdentifierPath) => {\n if (isIdentifierReferenced(ident)) return false\n if (!refs) return true\n return refs.has(ident)\n }\n\n const sweepFunction = (\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n ) => {\n const identifier = getIdentifier(path)\n if (identifier?.node && shouldBeRemoved(identifier)) {\n ++referencesRemovedInThisPass\n\n if (\n t.isAssignmentExpression(path.parentPath.node) ||\n t.isVariableDeclarator(path.parentPath.node)\n ) {\n path.parentPath.remove()\n } else {\n path.remove()\n }\n }\n }\n\n const sweepImport = (\n path: NodePath<\n | BabelTypes.ImportSpecifier\n | BabelTypes.ImportDefaultSpecifier\n | BabelTypes.ImportNamespaceSpecifier\n >,\n ) => {\n const local = path.get('local')\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n if (\n (path.parent as BabelTypes.ImportDeclaration).specifiers.length === 0\n ) {\n path.parentPath.remove()\n }\n }\n }\n\n // Traverse again to remove unused references. This happens at least once,\n // then repeats until no more references are removed.\n do {\n referencesRemovedInThisPass = 0\n\n programPath.scope.crawl()\n\n programPath.traverse({\n VariableDeclarator(path) {\n if (path.node.id.type === 'Identifier') {\n const local = path.get('id') as NodePath<BabelTypes.Identifier>\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n }\n } else if (path.node.id.type === 'ObjectPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const properties = pattern.get('properties')\n properties.forEach((property) => {\n const local = property.get(\n property.node.type === 'ObjectProperty'\n ? 'value'\n : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n property.node.type === 'RestElement'\n ? 'argument'\n : (function () {\n throw new Error('invariant')\n })(),\n ) as NodePath<BabelTypes.Identifier>\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n property.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('properties').length < 1\n ) {\n path.remove()\n }\n } else if (path.node.id.type === 'ArrayPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const elements = pattern.get('elements')\n elements.forEach((e) => {\n let local: NodePath<BabelTypes.Identifier>\n if (e.node?.type === 'Identifier') {\n local = e as NodePath<BabelTypes.Identifier>\n } else if (e.node?.type === 'RestElement') {\n local = e.get('argument') as NodePath<BabelTypes.Identifier>\n } else {\n return\n }\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n e.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('elements').length < 1\n ) {\n path.remove()\n }\n }\n },\n FunctionDeclaration: sweepFunction,\n FunctionExpression: sweepFunction,\n ArrowFunctionExpression: sweepFunction,\n ImportSpecifier: sweepImport,\n ImportDefaultSpecifier: sweepImport,\n ImportNamespaceSpecifier: sweepImport,\n })\n } while (referencesRemovedInThisPass)\n}\n\nfunction getIdentifier(\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n): NodePath<BabelTypes.Identifier> | null {\n const parentPath = path.parentPath\n if (parentPath.type === 'VariableDeclarator') {\n const variablePath = parentPath as NodePath<BabelTypes.VariableDeclarator>\n const name = variablePath.get('id')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (parentPath.type === 'AssignmentExpression') {\n const variablePath = parentPath as NodePath<BabelTypes.AssignmentExpression>\n const name = variablePath.get('left')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (path.node.type === 'ArrowFunctionExpression') {\n return null\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return path.node.id && path.node.id.type === 'Identifier'\n ? (path.get('id') as NodePath<BabelTypes.Identifier>)\n : null\n}\n\nfunction isIdentifierReferenced(\n ident: NodePath<BabelTypes.Identifier>,\n): boolean {\n const binding = ident.scope.getBinding(ident.node.name)\n if (binding?.referenced) {\n // Functions can reference themselves, so we need to check if there's a\n // binding outside the function scope or not.\n if (binding.path.type === 'FunctionDeclaration') {\n return !binding.constantViolations\n .concat(binding.referencePaths)\n // Check that every reference is contained within the function:\n .every((ref) => ref.findParent((parent) => parent === binding.path))\n }\n\n return true\n }\n return false\n}\n"],"names":["t"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eliminateUnreferencedIdentifiers.cjs","sources":["../../src/eliminateUnreferencedIdentifiers.ts"],"sourcesContent":["// Copied from https://github.com/pcattori/vite-env-only/blob/main/src/dce.ts\n// Adapted with some minor changes for the purpose of this project\n\nimport * as t from '@babel/types'\nimport type { types as BabelTypes } from '@babel/core'\nimport type { NodePath } from '@babel/traverse'\n\ntype IdentifierPath = NodePath<BabelTypes.Identifier>\n\n// export function findReferencedIdentifiers(\n// programPath: NodePath<BabelTypes.Program>,\n// ): Set<IdentifierPath> {\n// const refs = new Set<IdentifierPath>()\n\n// function markFunction(\n// path: NodePath<\n// | BabelTypes.FunctionDeclaration\n// | BabelTypes.FunctionExpression\n// | BabelTypes.ArrowFunctionExpression\n// >,\n// ) {\n// const ident = getIdentifier(path)\n// if (ident?.node && isIdentifierReferenced(ident)) {\n// refs.add(ident)\n// }\n// }\n\n// function markImport(\n// path: NodePath<\n// | BabelTypes.ImportSpecifier\n// | BabelTypes.ImportDefaultSpecifier\n// | BabelTypes.ImportNamespaceSpecifier\n// >,\n// ) {\n// const local = path.get('local')\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// }\n\n// programPath.traverse({\n// VariableDeclarator(path) {\n// if (path.node.id.type === 'Identifier') {\n// const local = path.get('id') as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// } else if (path.node.id.type === 'ObjectPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n// const properties = pattern.get('properties')\n// properties.forEach((p) => {\n// const local = p.get(\n// p.node.type === 'ObjectProperty'\n// ? 'value'\n// : p.node.type === 'RestElement'\n// ? 'argument'\n// : (function () {\n// throw new Error('invariant')\n// })(),\n// ) as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// } else if (path.node.id.type === 'ArrayPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n// const elements = pattern.get('elements')\n// elements.forEach((e) => {\n// let local: NodePath<BabelTypes.Identifier>\n// if (e.node?.type === 'Identifier') {\n// local = e as NodePath<BabelTypes.Identifier>\n// } else if (e.node?.type === 'RestElement') {\n// local = e.get('argument') as NodePath<BabelTypes.Identifier>\n// } else {\n// return\n// }\n\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// }\n// },\n\n// FunctionDeclaration: markFunction,\n// FunctionExpression: markFunction,\n// ArrowFunctionExpression: markFunction,\n// ImportSpecifier: markImport,\n// ImportDefaultSpecifier: markImport,\n// ImportNamespaceSpecifier: markImport,\n// })\n// return refs\n// }\n\n/**\n * @param refs - If provided, only these identifiers will be considered for removal.\n */\nexport const eliminateUnreferencedIdentifiers = (\n programPath: NodePath<BabelTypes.Program>,\n refs?: Set<IdentifierPath>,\n) => {\n let referencesRemovedInThisPass: number\n\n const shouldBeRemoved = (ident: IdentifierPath) => {\n if (isIdentifierReferenced(ident)) return false\n if (!refs) return true\n return refs.has(ident)\n }\n\n const sweepFunction = (\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n ) => {\n const identifier = getIdentifier(path)\n if (identifier?.node && shouldBeRemoved(identifier)) {\n ++referencesRemovedInThisPass\n\n if (\n t.isAssignmentExpression(path.parentPath.node) ||\n t.isVariableDeclarator(path.parentPath.node)\n ) {\n path.parentPath.remove()\n } else {\n path.remove()\n }\n }\n }\n\n const sweepImport = (\n path: NodePath<\n | BabelTypes.ImportSpecifier\n | BabelTypes.ImportDefaultSpecifier\n | BabelTypes.ImportNamespaceSpecifier\n >,\n ) => {\n const local = path.get('local')\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n if (\n (path.parent as BabelTypes.ImportDeclaration).specifiers.length === 0\n ) {\n path.parentPath.remove()\n }\n }\n }\n\n // Traverse again to remove unused references. This happens at least once,\n // then repeats until no more references are removed.\n do {\n referencesRemovedInThisPass = 0\n\n programPath.scope.crawl()\n\n programPath.traverse({\n VariableDeclarator(path) {\n if (path.node.id.type === 'Identifier') {\n const local = path.get('id') as NodePath<BabelTypes.Identifier>\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n }\n } else if (path.node.id.type === 'ObjectPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const properties = pattern.get('properties')\n properties.forEach((property) => {\n const local = property.get(\n property.node.type === 'ObjectProperty'\n ? 'value'\n : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n property.node.type === 'RestElement'\n ? 'argument'\n : (function () {\n throw new Error('invariant')\n })(),\n ) as NodePath<BabelTypes.Identifier>\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n property.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('properties').length < 1\n ) {\n path.remove()\n }\n } else if (path.node.id.type === 'ArrayPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n let hasRemoved = false as boolean\n\n pattern.get('elements').forEach((element, index) => {\n // if (!element) return // Skip holes in the pattern\n\n let identifierPath: NodePath<BabelTypes.Identifier>\n\n if (t.isIdentifier(element.node)) {\n identifierPath = element as NodePath<BabelTypes.Identifier>\n } else if (t.isRestElement(element.node)) {\n identifierPath = element.get(\n 'argument',\n ) as NodePath<BabelTypes.Identifier>\n } else {\n // For now, ignore other types like AssignmentPattern\n return\n }\n\n if (shouldBeRemoved(identifierPath)) {\n hasRemoved = true\n pattern.node.elements[index] = null // Remove the element by setting it to null\n }\n })\n\n // If any elements were removed and no elements are left, remove the entire declaration\n if (\n hasRemoved &&\n pattern.node.elements.every((element) => element === null)\n ) {\n path.remove()\n ++referencesRemovedInThisPass\n }\n }\n },\n FunctionDeclaration: sweepFunction,\n FunctionExpression: sweepFunction,\n ArrowFunctionExpression: sweepFunction,\n ImportSpecifier: sweepImport,\n ImportDefaultSpecifier: sweepImport,\n ImportNamespaceSpecifier: sweepImport,\n })\n } while (referencesRemovedInThisPass)\n}\n\nfunction getIdentifier(\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n): NodePath<BabelTypes.Identifier> | null {\n const parentPath = path.parentPath\n if (parentPath.type === 'VariableDeclarator') {\n const variablePath = parentPath as NodePath<BabelTypes.VariableDeclarator>\n const name = variablePath.get('id')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (parentPath.type === 'AssignmentExpression') {\n const variablePath = parentPath as NodePath<BabelTypes.AssignmentExpression>\n const name = variablePath.get('left')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (path.node.type === 'ArrowFunctionExpression') {\n return null\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return path.node.id && path.node.id.type === 'Identifier'\n ? (path.get('id') as NodePath<BabelTypes.Identifier>)\n : null\n}\n\nfunction isIdentifierReferenced(\n ident: NodePath<BabelTypes.Identifier>,\n): boolean {\n const binding = ident.scope.getBinding(ident.node.name)\n if (binding?.referenced) {\n // Functions can reference themselves, so we need to check if there's a\n // binding outside the function scope or not.\n if (binding.path.type === 'FunctionDeclaration') {\n return !binding.constantViolations\n .concat(binding.referencePaths)\n // Check that every reference is contained within the function:\n .every((ref) => ref.findParent((parent) => parent === binding.path))\n }\n\n return true\n }\n return false\n}\n"],"names":["t"],"mappings":"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"}
|
|
@@ -63,25 +63,26 @@ const eliminateUnreferencedIdentifiers = (programPath, refs) => {
|
|
|
63
63
|
}
|
|
64
64
|
} else if (path.node.id.type === "ArrayPattern") {
|
|
65
65
|
const pattern = path.get("id");
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if ((
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
66
|
+
let hasRemoved = false;
|
|
67
|
+
pattern.get("elements").forEach((element, index) => {
|
|
68
|
+
let identifierPath;
|
|
69
|
+
if (t.isIdentifier(element.node)) {
|
|
70
|
+
identifierPath = element;
|
|
71
|
+
} else if (t.isRestElement(element.node)) {
|
|
72
|
+
identifierPath = element.get(
|
|
73
|
+
"argument"
|
|
74
|
+
);
|
|
75
75
|
} else {
|
|
76
76
|
return;
|
|
77
77
|
}
|
|
78
|
-
if (shouldBeRemoved(
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
if (shouldBeRemoved(identifierPath)) {
|
|
79
|
+
hasRemoved = true;
|
|
80
|
+
pattern.node.elements[index] = null;
|
|
81
81
|
}
|
|
82
82
|
});
|
|
83
|
-
if (
|
|
83
|
+
if (hasRemoved && pattern.node.elements.every((element) => element === null)) {
|
|
84
84
|
path.remove();
|
|
85
|
+
++referencesRemovedInThisPass;
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eliminateUnreferencedIdentifiers.js","sources":["../../src/eliminateUnreferencedIdentifiers.ts"],"sourcesContent":["// Copied from https://github.com/pcattori/vite-env-only/blob/main/src/dce.ts\n// Adapted with some minor changes for the purpose of this project\n\nimport * as t from '@babel/types'\nimport type { types as BabelTypes } from '@babel/core'\nimport type { NodePath } from '@babel/traverse'\n\ntype IdentifierPath = NodePath<BabelTypes.Identifier>\n\n// export function findReferencedIdentifiers(\n// programPath: NodePath<BabelTypes.Program>,\n// ): Set<IdentifierPath> {\n// const refs = new Set<IdentifierPath>()\n\n// function markFunction(\n// path: NodePath<\n// | BabelTypes.FunctionDeclaration\n// | BabelTypes.FunctionExpression\n// | BabelTypes.ArrowFunctionExpression\n// >,\n// ) {\n// const ident = getIdentifier(path)\n// if (ident?.node && isIdentifierReferenced(ident)) {\n// refs.add(ident)\n// }\n// }\n\n// function markImport(\n// path: NodePath<\n// | BabelTypes.ImportSpecifier\n// | BabelTypes.ImportDefaultSpecifier\n// | BabelTypes.ImportNamespaceSpecifier\n// >,\n// ) {\n// const local = path.get('local')\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// }\n\n// programPath.traverse({\n// VariableDeclarator(path) {\n// if (path.node.id.type === 'Identifier') {\n// const local = path.get('id') as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// } else if (path.node.id.type === 'ObjectPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n// const properties = pattern.get('properties')\n// properties.forEach((p) => {\n// const local = p.get(\n// p.node.type === 'ObjectProperty'\n// ? 'value'\n// : p.node.type === 'RestElement'\n// ? 'argument'\n// : (function () {\n// throw new Error('invariant')\n// })(),\n// ) as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// } else if (path.node.id.type === 'ArrayPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n// const elements = pattern.get('elements')\n// elements.forEach((e) => {\n// let local: NodePath<BabelTypes.Identifier>\n// if (e.node?.type === 'Identifier') {\n// local = e as NodePath<BabelTypes.Identifier>\n// } else if (e.node?.type === 'RestElement') {\n// local = e.get('argument') as NodePath<BabelTypes.Identifier>\n// } else {\n// return\n// }\n\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// }\n// },\n\n// FunctionDeclaration: markFunction,\n// FunctionExpression: markFunction,\n// ArrowFunctionExpression: markFunction,\n// ImportSpecifier: markImport,\n// ImportDefaultSpecifier: markImport,\n// ImportNamespaceSpecifier: markImport,\n// })\n// return refs\n// }\n\n/**\n * @param refs - If provided, only these identifiers will be considered for removal.\n */\nexport const eliminateUnreferencedIdentifiers = (\n programPath: NodePath<BabelTypes.Program>,\n refs?: Set<IdentifierPath>,\n) => {\n let referencesRemovedInThisPass: number\n\n const shouldBeRemoved = (ident: IdentifierPath) => {\n if (isIdentifierReferenced(ident)) return false\n if (!refs) return true\n return refs.has(ident)\n }\n\n const sweepFunction = (\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n ) => {\n const identifier = getIdentifier(path)\n if (identifier?.node && shouldBeRemoved(identifier)) {\n ++referencesRemovedInThisPass\n\n if (\n t.isAssignmentExpression(path.parentPath.node) ||\n t.isVariableDeclarator(path.parentPath.node)\n ) {\n path.parentPath.remove()\n } else {\n path.remove()\n }\n }\n }\n\n const sweepImport = (\n path: NodePath<\n | BabelTypes.ImportSpecifier\n | BabelTypes.ImportDefaultSpecifier\n | BabelTypes.ImportNamespaceSpecifier\n >,\n ) => {\n const local = path.get('local')\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n if (\n (path.parent as BabelTypes.ImportDeclaration).specifiers.length === 0\n ) {\n path.parentPath.remove()\n }\n }\n }\n\n // Traverse again to remove unused references. This happens at least once,\n // then repeats until no more references are removed.\n do {\n referencesRemovedInThisPass = 0\n\n programPath.scope.crawl()\n\n programPath.traverse({\n VariableDeclarator(path) {\n if (path.node.id.type === 'Identifier') {\n const local = path.get('id') as NodePath<BabelTypes.Identifier>\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n }\n } else if (path.node.id.type === 'ObjectPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const properties = pattern.get('properties')\n properties.forEach((property) => {\n const local = property.get(\n property.node.type === 'ObjectProperty'\n ? 'value'\n : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n property.node.type === 'RestElement'\n ? 'argument'\n : (function () {\n throw new Error('invariant')\n })(),\n ) as NodePath<BabelTypes.Identifier>\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n property.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('properties').length < 1\n ) {\n path.remove()\n }\n } else if (path.node.id.type === 'ArrayPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const elements = pattern.get('elements')\n elements.forEach((e) => {\n let local: NodePath<BabelTypes.Identifier>\n if (e.node?.type === 'Identifier') {\n local = e as NodePath<BabelTypes.Identifier>\n } else if (e.node?.type === 'RestElement') {\n local = e.get('argument') as NodePath<BabelTypes.Identifier>\n } else {\n return\n }\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n e.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('elements').length < 1\n ) {\n path.remove()\n }\n }\n },\n FunctionDeclaration: sweepFunction,\n FunctionExpression: sweepFunction,\n ArrowFunctionExpression: sweepFunction,\n ImportSpecifier: sweepImport,\n ImportDefaultSpecifier: sweepImport,\n ImportNamespaceSpecifier: sweepImport,\n })\n } while (referencesRemovedInThisPass)\n}\n\nfunction getIdentifier(\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n): NodePath<BabelTypes.Identifier> | null {\n const parentPath = path.parentPath\n if (parentPath.type === 'VariableDeclarator') {\n const variablePath = parentPath as NodePath<BabelTypes.VariableDeclarator>\n const name = variablePath.get('id')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (parentPath.type === 'AssignmentExpression') {\n const variablePath = parentPath as NodePath<BabelTypes.AssignmentExpression>\n const name = variablePath.get('left')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (path.node.type === 'ArrowFunctionExpression') {\n return null\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return path.node.id && path.node.id.type === 'Identifier'\n ? (path.get('id') as NodePath<BabelTypes.Identifier>)\n : null\n}\n\nfunction isIdentifierReferenced(\n ident: NodePath<BabelTypes.Identifier>,\n): boolean {\n const binding = ident.scope.getBinding(ident.node.name)\n if (binding?.referenced) {\n // Functions can reference themselves, so we need to check if there's a\n // binding outside the function scope or not.\n if (binding.path.type === 'FunctionDeclaration') {\n return !binding.constantViolations\n .concat(binding.referencePaths)\n // Check that every reference is contained within the function:\n .every((ref) => ref.findParent((parent) => parent === binding.path))\n }\n\n return true\n }\n return false\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eliminateUnreferencedIdentifiers.js","sources":["../../src/eliminateUnreferencedIdentifiers.ts"],"sourcesContent":["// Copied from https://github.com/pcattori/vite-env-only/blob/main/src/dce.ts\n// Adapted with some minor changes for the purpose of this project\n\nimport * as t from '@babel/types'\nimport type { types as BabelTypes } from '@babel/core'\nimport type { NodePath } from '@babel/traverse'\n\ntype IdentifierPath = NodePath<BabelTypes.Identifier>\n\n// export function findReferencedIdentifiers(\n// programPath: NodePath<BabelTypes.Program>,\n// ): Set<IdentifierPath> {\n// const refs = new Set<IdentifierPath>()\n\n// function markFunction(\n// path: NodePath<\n// | BabelTypes.FunctionDeclaration\n// | BabelTypes.FunctionExpression\n// | BabelTypes.ArrowFunctionExpression\n// >,\n// ) {\n// const ident = getIdentifier(path)\n// if (ident?.node && isIdentifierReferenced(ident)) {\n// refs.add(ident)\n// }\n// }\n\n// function markImport(\n// path: NodePath<\n// | BabelTypes.ImportSpecifier\n// | BabelTypes.ImportDefaultSpecifier\n// | BabelTypes.ImportNamespaceSpecifier\n// >,\n// ) {\n// const local = path.get('local')\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// }\n\n// programPath.traverse({\n// VariableDeclarator(path) {\n// if (path.node.id.type === 'Identifier') {\n// const local = path.get('id') as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// } else if (path.node.id.type === 'ObjectPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n// const properties = pattern.get('properties')\n// properties.forEach((p) => {\n// const local = p.get(\n// p.node.type === 'ObjectProperty'\n// ? 'value'\n// : p.node.type === 'RestElement'\n// ? 'argument'\n// : (function () {\n// throw new Error('invariant')\n// })(),\n// ) as NodePath<BabelTypes.Identifier>\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// } else if (path.node.id.type === 'ArrayPattern') {\n// const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n// const elements = pattern.get('elements')\n// elements.forEach((e) => {\n// let local: NodePath<BabelTypes.Identifier>\n// if (e.node?.type === 'Identifier') {\n// local = e as NodePath<BabelTypes.Identifier>\n// } else if (e.node?.type === 'RestElement') {\n// local = e.get('argument') as NodePath<BabelTypes.Identifier>\n// } else {\n// return\n// }\n\n// if (isIdentifierReferenced(local)) {\n// refs.add(local)\n// }\n// })\n// }\n// },\n\n// FunctionDeclaration: markFunction,\n// FunctionExpression: markFunction,\n// ArrowFunctionExpression: markFunction,\n// ImportSpecifier: markImport,\n// ImportDefaultSpecifier: markImport,\n// ImportNamespaceSpecifier: markImport,\n// })\n// return refs\n// }\n\n/**\n * @param refs - If provided, only these identifiers will be considered for removal.\n */\nexport const eliminateUnreferencedIdentifiers = (\n programPath: NodePath<BabelTypes.Program>,\n refs?: Set<IdentifierPath>,\n) => {\n let referencesRemovedInThisPass: number\n\n const shouldBeRemoved = (ident: IdentifierPath) => {\n if (isIdentifierReferenced(ident)) return false\n if (!refs) return true\n return refs.has(ident)\n }\n\n const sweepFunction = (\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n ) => {\n const identifier = getIdentifier(path)\n if (identifier?.node && shouldBeRemoved(identifier)) {\n ++referencesRemovedInThisPass\n\n if (\n t.isAssignmentExpression(path.parentPath.node) ||\n t.isVariableDeclarator(path.parentPath.node)\n ) {\n path.parentPath.remove()\n } else {\n path.remove()\n }\n }\n }\n\n const sweepImport = (\n path: NodePath<\n | BabelTypes.ImportSpecifier\n | BabelTypes.ImportDefaultSpecifier\n | BabelTypes.ImportNamespaceSpecifier\n >,\n ) => {\n const local = path.get('local')\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n if (\n (path.parent as BabelTypes.ImportDeclaration).specifiers.length === 0\n ) {\n path.parentPath.remove()\n }\n }\n }\n\n // Traverse again to remove unused references. This happens at least once,\n // then repeats until no more references are removed.\n do {\n referencesRemovedInThisPass = 0\n\n programPath.scope.crawl()\n\n programPath.traverse({\n VariableDeclarator(path) {\n if (path.node.id.type === 'Identifier') {\n const local = path.get('id') as NodePath<BabelTypes.Identifier>\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n path.remove()\n }\n } else if (path.node.id.type === 'ObjectPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ObjectPattern>\n\n const beforeCount = referencesRemovedInThisPass\n const properties = pattern.get('properties')\n properties.forEach((property) => {\n const local = property.get(\n property.node.type === 'ObjectProperty'\n ? 'value'\n : // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n property.node.type === 'RestElement'\n ? 'argument'\n : (function () {\n throw new Error('invariant')\n })(),\n ) as NodePath<BabelTypes.Identifier>\n\n if (shouldBeRemoved(local)) {\n ++referencesRemovedInThisPass\n property.remove()\n }\n })\n\n if (\n beforeCount !== referencesRemovedInThisPass &&\n pattern.get('properties').length < 1\n ) {\n path.remove()\n }\n } else if (path.node.id.type === 'ArrayPattern') {\n const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>\n\n let hasRemoved = false as boolean\n\n pattern.get('elements').forEach((element, index) => {\n // if (!element) return // Skip holes in the pattern\n\n let identifierPath: NodePath<BabelTypes.Identifier>\n\n if (t.isIdentifier(element.node)) {\n identifierPath = element as NodePath<BabelTypes.Identifier>\n } else if (t.isRestElement(element.node)) {\n identifierPath = element.get(\n 'argument',\n ) as NodePath<BabelTypes.Identifier>\n } else {\n // For now, ignore other types like AssignmentPattern\n return\n }\n\n if (shouldBeRemoved(identifierPath)) {\n hasRemoved = true\n pattern.node.elements[index] = null // Remove the element by setting it to null\n }\n })\n\n // If any elements were removed and no elements are left, remove the entire declaration\n if (\n hasRemoved &&\n pattern.node.elements.every((element) => element === null)\n ) {\n path.remove()\n ++referencesRemovedInThisPass\n }\n }\n },\n FunctionDeclaration: sweepFunction,\n FunctionExpression: sweepFunction,\n ArrowFunctionExpression: sweepFunction,\n ImportSpecifier: sweepImport,\n ImportDefaultSpecifier: sweepImport,\n ImportNamespaceSpecifier: sweepImport,\n })\n } while (referencesRemovedInThisPass)\n}\n\nfunction getIdentifier(\n path: NodePath<\n | BabelTypes.FunctionDeclaration\n | BabelTypes.FunctionExpression\n | BabelTypes.ArrowFunctionExpression\n >,\n): NodePath<BabelTypes.Identifier> | null {\n const parentPath = path.parentPath\n if (parentPath.type === 'VariableDeclarator') {\n const variablePath = parentPath as NodePath<BabelTypes.VariableDeclarator>\n const name = variablePath.get('id')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (parentPath.type === 'AssignmentExpression') {\n const variablePath = parentPath as NodePath<BabelTypes.AssignmentExpression>\n const name = variablePath.get('left')\n return name.node.type === 'Identifier'\n ? (name as NodePath<BabelTypes.Identifier>)\n : null\n }\n\n if (path.node.type === 'ArrowFunctionExpression') {\n return null\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n return path.node.id && path.node.id.type === 'Identifier'\n ? (path.get('id') as NodePath<BabelTypes.Identifier>)\n : null\n}\n\nfunction isIdentifierReferenced(\n ident: NodePath<BabelTypes.Identifier>,\n): boolean {\n const binding = ident.scope.getBinding(ident.node.name)\n if (binding?.referenced) {\n // Functions can reference themselves, so we need to check if there's a\n // binding outside the function scope or not.\n if (binding.path.type === 'FunctionDeclaration') {\n return !binding.constantViolations\n .concat(binding.referencePaths)\n // Check that every reference is contained within the function:\n .every((ref) => ref.findParent((parent) => parent === binding.path))\n }\n\n return true\n }\n return false\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/router-vite-plugin",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.10",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"@types/babel__traverse": "^7.20.5",
|
|
65
65
|
"@vitejs/plugin-react": "^4.2.1",
|
|
66
66
|
"zod": "^3.22.4",
|
|
67
|
-
"@tanstack/router-generator": "1.
|
|
67
|
+
"@tanstack/router-generator": "1.26.10"
|
|
68
68
|
},
|
|
69
69
|
"scripts": {
|
|
70
70
|
"clean": "rimraf ./dist && rimraf ./coverage",
|
|
@@ -197,29 +197,37 @@ export const eliminateUnreferencedIdentifiers = (
|
|
|
197
197
|
} else if (path.node.id.type === 'ArrayPattern') {
|
|
198
198
|
const pattern = path.get('id') as NodePath<BabelTypes.ArrayPattern>
|
|
199
199
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
elements.forEach((
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
200
|
+
let hasRemoved = false as boolean
|
|
201
|
+
|
|
202
|
+
pattern.get('elements').forEach((element, index) => {
|
|
203
|
+
// if (!element) return // Skip holes in the pattern
|
|
204
|
+
|
|
205
|
+
let identifierPath: NodePath<BabelTypes.Identifier>
|
|
206
|
+
|
|
207
|
+
if (t.isIdentifier(element.node)) {
|
|
208
|
+
identifierPath = element as NodePath<BabelTypes.Identifier>
|
|
209
|
+
} else if (t.isRestElement(element.node)) {
|
|
210
|
+
identifierPath = element.get(
|
|
211
|
+
'argument',
|
|
212
|
+
) as NodePath<BabelTypes.Identifier>
|
|
208
213
|
} else {
|
|
214
|
+
// For now, ignore other types like AssignmentPattern
|
|
209
215
|
return
|
|
210
216
|
}
|
|
211
217
|
|
|
212
|
-
if (shouldBeRemoved(
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
if (shouldBeRemoved(identifierPath)) {
|
|
219
|
+
hasRemoved = true
|
|
220
|
+
pattern.node.elements[index] = null // Remove the element by setting it to null
|
|
215
221
|
}
|
|
216
222
|
})
|
|
217
223
|
|
|
224
|
+
// If any elements were removed and no elements are left, remove the entire declaration
|
|
218
225
|
if (
|
|
219
|
-
|
|
220
|
-
pattern.
|
|
226
|
+
hasRemoved &&
|
|
227
|
+
pattern.node.elements.every((element) => element === null)
|
|
221
228
|
) {
|
|
222
229
|
path.remove()
|
|
230
|
+
++referencesRemovedInThisPass
|
|
223
231
|
}
|
|
224
232
|
}
|
|
225
233
|
},
|
package/src/tests/index.test.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { readFile, readdir } from 'fs/promises'
|
|
2
|
-
import path from 'path'
|
|
3
|
-
import { expect, test } from 'vitest'
|
|
4
|
-
import { compileFile, makeCompile, splitFile } from '../compilers'
|
|
5
|
-
import { splitPrefix } from '../constants'
|
|
6
|
-
|
|
7
|
-
test('it compiles and splits', async () => {
|
|
8
|
-
// get the list of files from the /test-files directory
|
|
9
|
-
const files = await readdir(path.resolve(__dirname, './test-files'))
|
|
10
|
-
for (const file of files) {
|
|
11
|
-
console.log('Testing:', file)
|
|
12
|
-
await compileTestFile({ file })
|
|
13
|
-
await splitTestFile({ file })
|
|
14
|
-
}
|
|
15
|
-
})
|
|
16
|
-
|
|
17
|
-
async function compileTestFile(opts: { file: string }) {
|
|
18
|
-
const code = (
|
|
19
|
-
await readFile(path.resolve(__dirname, `./test-files/${opts.file}`))
|
|
20
|
-
).toString()
|
|
21
|
-
|
|
22
|
-
// console.log('Compiling...')
|
|
23
|
-
// console.log('⬇️⬇️⬇️⬇️⬇️')
|
|
24
|
-
// console.log()
|
|
25
|
-
const result = await compileFile({
|
|
26
|
-
code,
|
|
27
|
-
compile: makeCompile({
|
|
28
|
-
root: path.resolve(__dirname, './test-files'),
|
|
29
|
-
}),
|
|
30
|
-
filename: `${opts.file}`,
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
// console.log(result.code)
|
|
34
|
-
// console.log()
|
|
35
|
-
|
|
36
|
-
await expect(result.code).toMatchFileSnapshot(`./snapshots/${opts.file}`)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
async function splitTestFile(opts: { file: string }) {
|
|
40
|
-
const code = (
|
|
41
|
-
await readFile(path.resolve(__dirname, `./test-files/${opts.file}`))
|
|
42
|
-
).toString()
|
|
43
|
-
|
|
44
|
-
// console.log('Splitting...')
|
|
45
|
-
// console.log('⬇️⬇️⬇️⬇️⬇️')
|
|
46
|
-
// console.log()
|
|
47
|
-
const result = await splitFile({
|
|
48
|
-
code,
|
|
49
|
-
compile: makeCompile({
|
|
50
|
-
root: path.resolve(__dirname, './test-files'),
|
|
51
|
-
}),
|
|
52
|
-
filename: `${opts.file}?${splitPrefix}`,
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
// console.log(result.code)
|
|
56
|
-
// console.log()
|
|
57
|
-
await expect(result.code).toMatchFileSnapshot(
|
|
58
|
-
`./snapshots/${opts.file.replace('.tsx', '')}?split.tsx`,
|
|
59
|
-
)
|
|
60
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { lazyRouteComponent } from '@tanstack/react-router';
|
|
2
|
-
const $$splitComponentImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/function-declaration.tsx?tsr-split');
|
|
3
|
-
import { lazyFn } from '@tanstack/react-router';
|
|
4
|
-
const $$splitLoaderImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/function-declaration.tsx?tsr-split');
|
|
5
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
6
|
-
import '../posts';
|
|
7
|
-
export const Route = createFileRoute('/posts')({
|
|
8
|
-
loader: lazyFn($$splitLoaderImporter, 'loader'),
|
|
9
|
-
component: lazyRouteComponent($$splitComponentImporter, 'component')
|
|
10
|
-
});
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Link, Outlet } from '@tanstack/react-router';
|
|
2
|
-
import { fetchPosts } from '../posts';
|
|
3
|
-
import { Route } from "function-declaration.tsx";
|
|
4
|
-
const component = function PostsComponent() {
|
|
5
|
-
const posts = Route.useLoaderData();
|
|
6
|
-
return <div className="p-2 flex gap-2">
|
|
7
|
-
<ul className="list-disc pl-4">
|
|
8
|
-
{[...posts, {
|
|
9
|
-
id: 'i-do-not-exist',
|
|
10
|
-
title: 'Non-existent Post'
|
|
11
|
-
}]?.map(post => {
|
|
12
|
-
return <li key={post.id} className="whitespace-nowrap">
|
|
13
|
-
<Link to="/posts/$postId" params={{
|
|
14
|
-
postId: post.id
|
|
15
|
-
}} className="block py-1 text-blue-800 hover:text-blue-600" activeProps={{
|
|
16
|
-
className: 'text-black font-bold'
|
|
17
|
-
}}>
|
|
18
|
-
<div>{post.title.substring(0, 20)}</div>
|
|
19
|
-
</Link>
|
|
20
|
-
</li>;
|
|
21
|
-
})}
|
|
22
|
-
</ul>
|
|
23
|
-
<hr />
|
|
24
|
-
<Outlet />
|
|
25
|
-
</div>;
|
|
26
|
-
};
|
|
27
|
-
export { component };
|
|
28
|
-
const loader = fetchPosts;
|
|
29
|
-
export { loader };
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { lazyFn } from '@tanstack/react-router';
|
|
2
|
-
const $$splitLoaderImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/imported.tsx?tsr-split');
|
|
3
|
-
import { lazyRouteComponent } from '@tanstack/react-router';
|
|
4
|
-
const $$splitComponentImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/imported.tsx?tsr-split');
|
|
5
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
6
|
-
import '../shared/imported';
|
|
7
|
-
export const Route = createFileRoute('/')({
|
|
8
|
-
component: lazyRouteComponent($$splitComponentImporter, 'component'),
|
|
9
|
-
loader: lazyFn($$splitLoaderImporter, 'loader')
|
|
10
|
-
});
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { lazyRouteComponent } from '@tanstack/react-router';
|
|
2
|
-
const $$splitComponentImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/inline.tsx?tsr-split');
|
|
3
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
4
|
-
export const Route = createFileRoute('/')({
|
|
5
|
-
component: lazyRouteComponent($$splitComponentImporter, 'component')
|
|
6
|
-
});
|
|
7
|
-
Route.addChildren([]);
|
|
8
|
-
export const test = 'test';
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import * as styles from '../style.css';
|
|
2
|
-
import { TEST_DATA } from '../test.const';
|
|
3
|
-
const Button = (props: {
|
|
4
|
-
children: any;
|
|
5
|
-
}) => {
|
|
6
|
-
return <button>{props.children}</button>;
|
|
7
|
-
};
|
|
8
|
-
import { Route } from "inline.tsx";
|
|
9
|
-
Route.addChildren([]);
|
|
10
|
-
import { test } from "inline.tsx";
|
|
11
|
-
const component = () => {
|
|
12
|
-
return <div className="p-2">
|
|
13
|
-
{test}
|
|
14
|
-
<h3 className={styles.indexPageTitle}>{TEST_DATA.welcome}</h3>
|
|
15
|
-
<Button>Click me</Button>
|
|
16
|
-
</div>;
|
|
17
|
-
};
|
|
18
|
-
export { component };
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { lazyRouteComponent } from '@tanstack/react-router';
|
|
2
|
-
const $$splitComponentImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/random-number.tsx?tsr-split');
|
|
3
|
-
import { lazyFn } from '@tanstack/react-router';
|
|
4
|
-
const $$splitLoaderImporter = () => import('tsr-split:/Users/tannerlinsley/GitHub/router/packages/router-vite-plugin/random-number.tsx?tsr-split');
|
|
5
|
-
import { createFileRoute } from '@tanstack/react-router';
|
|
6
|
-
export const textColors = [`text-rose-500`, `text-yellow-500`, `text-teal-500`, `text-blue-500`];
|
|
7
|
-
export const gradients = [`from-rose-500 to-yellow-500`, `from-yellow-500 to-teal-500`, `from-teal-500 to-violet-500`, `from-blue-500 to-pink-500`];
|
|
8
|
-
export const Route = createFileRoute('/')({
|
|
9
|
-
loader: lazyFn($$splitLoaderImporter, 'loader'),
|
|
10
|
-
component: lazyRouteComponent($$splitComponentImporter, 'component')
|
|
11
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { defer } from '@tanstack/react-router';
|
|
2
|
-
import { getSponsorsForSponsorPack } from '~/server/sponsors';
|
|
3
|
-
import discordImage from '~/images/discord-logo-white.svg';
|
|
4
|
-
import { sample } from '~/utils/utils';
|
|
5
|
-
import { textColors } from "random-number.tsx";
|
|
6
|
-
import { gradients } from "random-number.tsx";
|
|
7
|
-
import { Route } from "random-number.tsx";
|
|
8
|
-
const component = function Index() {
|
|
9
|
-
const {
|
|
10
|
-
randomNumber
|
|
11
|
-
} = Route.useLoaderData();
|
|
12
|
-
const gradient = sample(gradients, randomNumber);
|
|
13
|
-
const textColor = sample(textColors, randomNumber);
|
|
14
|
-
return <>
|
|
15
|
-
{discordImage}
|
|
16
|
-
{gradient}
|
|
17
|
-
{textColor}
|
|
18
|
-
</>;
|
|
19
|
-
};
|
|
20
|
-
export { component };
|
|
21
|
-
const loader = () => {
|
|
22
|
-
return {
|
|
23
|
-
randomNumber: Math.random(),
|
|
24
|
-
sponsorsPromise: defer(getSponsorsForSponsorPack())
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
|
-
export { loader };
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import { createFileRoute, Link, Outlet } from '@tanstack/react-router'
|
|
3
|
-
import { fetchPosts } from '../posts'
|
|
4
|
-
|
|
5
|
-
export const Route = createFileRoute('/posts')({
|
|
6
|
-
loader: fetchPosts,
|
|
7
|
-
component: PostsComponent,
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
function PostsComponent() {
|
|
11
|
-
const posts = Route.useLoaderData()
|
|
12
|
-
|
|
13
|
-
return (
|
|
14
|
-
<div className="p-2 flex gap-2">
|
|
15
|
-
<ul className="list-disc pl-4">
|
|
16
|
-
{[...posts, { id: 'i-do-not-exist', title: 'Non-existent Post' }]?.map(
|
|
17
|
-
(post) => {
|
|
18
|
-
return (
|
|
19
|
-
<li key={post.id} className="whitespace-nowrap">
|
|
20
|
-
<Link
|
|
21
|
-
to="/posts/$postId"
|
|
22
|
-
params={{
|
|
23
|
-
postId: post.id,
|
|
24
|
-
}}
|
|
25
|
-
className="block py-1 text-blue-800 hover:text-blue-600"
|
|
26
|
-
activeProps={{ className: 'text-black font-bold' }}
|
|
27
|
-
>
|
|
28
|
-
<div>{post.title.substring(0, 20)}</div>
|
|
29
|
-
</Link>
|
|
30
|
-
</li>
|
|
31
|
-
)
|
|
32
|
-
},
|
|
33
|
-
)}
|
|
34
|
-
</ul>
|
|
35
|
-
<hr />
|
|
36
|
-
<Outlet />
|
|
37
|
-
</div>
|
|
38
|
-
)
|
|
39
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import { createFileRoute } from '@tanstack/react-router'
|
|
3
|
-
|
|
4
|
-
import * as styles from '../style.css'
|
|
5
|
-
import { TEST_DATA } from '../test.const'
|
|
6
|
-
|
|
7
|
-
const Button = (props: { children: any }) => {
|
|
8
|
-
return <button>{props.children}</button>
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const Route = createFileRoute('/')({
|
|
12
|
-
component: () => {
|
|
13
|
-
return (
|
|
14
|
-
<div className="p-2">
|
|
15
|
-
{test}
|
|
16
|
-
<h3 className={styles.indexPageTitle}>{TEST_DATA.welcome}</h3>
|
|
17
|
-
<Button>Click me</Button>
|
|
18
|
-
</div>
|
|
19
|
-
)
|
|
20
|
-
},
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
Route.addChildren([])
|
|
24
|
-
|
|
25
|
-
export const test = 'test'
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { Await, Link, createFileRoute, defer } from '@tanstack/react-router'
|
|
2
|
-
import { Carbon } from '~/components/Carbon'
|
|
3
|
-
import { twMerge } from 'tailwind-merge'
|
|
4
|
-
import { FaDiscord, FaGithub, FaTshirt } from 'react-icons/fa'
|
|
5
|
-
import { CgMusicSpeaker, CgSpinner } from 'react-icons/cg'
|
|
6
|
-
import { Footer } from '~/components/Footer'
|
|
7
|
-
import SponsorPack from '~/components/SponsorPack'
|
|
8
|
-
import { LogoColor } from '~/components/LogoColor'
|
|
9
|
-
import { getSponsorsForSponsorPack } from '~/server/sponsors'
|
|
10
|
-
import discordImage from '~/images/discord-logo-white.svg'
|
|
11
|
-
import agGridImage from '~/images/ag-grid.png'
|
|
12
|
-
import nozzleImage from '~/images/nozzle.png'
|
|
13
|
-
import bytesImage from '~/images/bytes.svg'
|
|
14
|
-
import bytesUidotdevImage from '~/images/bytes-uidotdev.png'
|
|
15
|
-
import { useMutation } from '~/hooks/useMutation'
|
|
16
|
-
import { sample } from '~/utils/utils'
|
|
17
|
-
|
|
18
|
-
export const textColors = [
|
|
19
|
-
`text-rose-500`,
|
|
20
|
-
`text-yellow-500`,
|
|
21
|
-
`text-teal-500`,
|
|
22
|
-
`text-blue-500`,
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
export const gradients = [
|
|
26
|
-
`from-rose-500 to-yellow-500`,
|
|
27
|
-
`from-yellow-500 to-teal-500`,
|
|
28
|
-
`from-teal-500 to-violet-500`,
|
|
29
|
-
`from-blue-500 to-pink-500`,
|
|
30
|
-
]
|
|
31
|
-
|
|
32
|
-
const courses = [
|
|
33
|
-
{
|
|
34
|
-
name: 'The Official TanStack React Query Course',
|
|
35
|
-
cardStyles: `border-t-4 border-red-500 hover:(border-green-500)`,
|
|
36
|
-
href: 'https://query.gg/?s=tanstack',
|
|
37
|
-
description: `Learn how to build enterprise quality apps with TanStack's React Query the easy way with our brand new course.`,
|
|
38
|
-
},
|
|
39
|
-
]
|
|
40
|
-
|
|
41
|
-
export const Route = createFileRoute('/')({
|
|
42
|
-
loader: () => {
|
|
43
|
-
return {
|
|
44
|
-
randomNumber: Math.random(),
|
|
45
|
-
sponsorsPromise: defer(getSponsorsForSponsorPack()),
|
|
46
|
-
}
|
|
47
|
-
},
|
|
48
|
-
component: Index,
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
async function bytesSignupServerFn({ email }: { email: string }) {
|
|
52
|
-
'use server'
|
|
53
|
-
|
|
54
|
-
return fetch(`https://bytes.dev/api/bytes-optin-cors`, {
|
|
55
|
-
method: 'POST',
|
|
56
|
-
body: JSON.stringify({
|
|
57
|
-
email,
|
|
58
|
-
influencer: 'tanstack',
|
|
59
|
-
}),
|
|
60
|
-
headers: {
|
|
61
|
-
Accept: 'application/json',
|
|
62
|
-
'Content-Type': 'application/json',
|
|
63
|
-
},
|
|
64
|
-
})
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function Index() {
|
|
68
|
-
const bytesSignupMutation = useMutation({
|
|
69
|
-
fn: bytesSignupServerFn,
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
const { sponsorsPromise, randomNumber, testing2 } = Route.useLoaderData()
|
|
73
|
-
const gradient = sample(gradients, randomNumber)
|
|
74
|
-
const textColor = sample(textColors, randomNumber)
|
|
75
|
-
|
|
76
|
-
return (
|
|
77
|
-
<>
|
|
78
|
-
{discordImage}
|
|
79
|
-
{gradient}
|
|
80
|
-
{textColor}
|
|
81
|
-
</>
|
|
82
|
-
)
|
|
83
|
-
}
|