feat: 导航收藏网站 v1.0

功能:
- 网站收藏管理(添加/编辑/删除/收藏)
- 分类管理(支持自定义图标和颜色)
- 搜索功能
- 点击统计
- 现代暗色主题 UI

技术栈:
- 后端: Python Flask + MySQL
- 前端: React + Vite + Tailwind CSS
- 数据库: MySQL (192.168.8.160)
- 端口: 后端 5003, 前端 5173
This commit is contained in:
小龙
2026-04-06 10:40:43 +00:00
commit a1951c3aeb
6825 changed files with 939030 additions and 0 deletions
+84
View File
@@ -0,0 +1,84 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
class Binding {
constructor({
identifier,
scope,
path,
kind
}) {
this.identifier = void 0;
this.scope = void 0;
this.path = void 0;
this.kind = void 0;
this.constantViolations = [];
this.constant = true;
this.referencePaths = [];
this.referenced = false;
this.references = 0;
this.identifier = identifier;
this.scope = scope;
this.path = path;
this.kind = kind;
if ((kind === "var" || kind === "hoisted") && isInitInLoop(path)) {
this.reassign(path);
}
this.clearValue();
}
deoptValue() {
this.clearValue();
this.hasDeoptedValue = true;
}
setValue(value) {
if (this.hasDeoptedValue) return;
this.hasValue = true;
this.value = value;
}
clearValue() {
this.hasDeoptedValue = false;
this.hasValue = false;
this.value = null;
}
reassign(path) {
this.constant = false;
if (this.constantViolations.includes(path)) {
return;
}
this.constantViolations.push(path);
}
reference(path) {
if (this.referencePaths.includes(path)) {
return;
}
this.referenced = true;
this.references++;
this.referencePaths.push(path);
}
dereference() {
this.references--;
this.referenced = !!this.references;
}
}
exports.default = Binding;
function isInitInLoop(path) {
const isFunctionDeclarationOrHasInit = !path.isVariableDeclarator() || path.node.init;
for (let {
parentPath,
key
} = path; parentPath; {
parentPath,
key
} = parentPath) {
if (parentPath.isFunctionParent()) return false;
if (key === "left" && parentPath.isForXStatement() || isFunctionDeclarationOrHasInit && key === "body" && parentPath.isLoop()) {
return true;
}
}
return false;
}
//# sourceMappingURL=binding.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+132
View File
@@ -0,0 +1,132 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var t = require("@babel/types");
var _t = t;
var _traverseNode = require("../../traverse-node.js");
var _visitors = require("../../visitors.js");
var _context = require("../../path/context.js");
const {
getAssignmentIdentifiers
} = _t;
const renameVisitor = {
ReferencedIdentifier({
node
}, state) {
if (node.name === state.oldName) {
node.name = state.newName;
}
},
Scope(path, state) {
if (!path.scope.bindingIdentifierEquals(state.oldName, state.binding.identifier)) {
path.skip();
if (path.isMethod()) {
if (!path.requeueComputedKeyAndDecorators) {
_context.requeueComputedKeyAndDecorators.call(path);
} else {
path.requeueComputedKeyAndDecorators();
}
}
if (path.isSwitchStatement()) {
path.context.maybeQueue(path.get("discriminant"));
}
}
},
ObjectProperty({
node,
scope
}, state) {
const {
name
} = node.key;
if (node.shorthand && (name === state.oldName || name === state.newName) && scope.getBindingIdentifier(name) === state.binding.identifier) {
var _node$extra;
node.shorthand = false;
if ((_node$extra = node.extra) != null && _node$extra.shorthand) node.extra.shorthand = false;
}
},
"AssignmentExpression|Declaration|VariableDeclarator"(path, state) {
if (path.isVariableDeclaration()) return;
const ids = path.isAssignmentExpression() ? getAssignmentIdentifiers(path.node) : path.getOuterBindingIdentifiers();
for (const name in ids) {
if (name === state.oldName) ids[name].name = state.newName;
}
}
};
class Renamer {
constructor(binding, oldName, newName) {
this.newName = newName;
this.oldName = oldName;
this.binding = binding;
}
maybeConvertFromExportDeclaration(parentDeclar) {
const maybeExportDeclar = parentDeclar.parentPath;
if (!maybeExportDeclar.isExportDeclaration()) {
return;
}
if (maybeExportDeclar.isExportDefaultDeclaration()) {
const {
declaration
} = maybeExportDeclar.node;
if (t.isDeclaration(declaration) && !declaration.id) {
return;
}
}
if (maybeExportDeclar.isExportAllDeclaration()) {
return;
}
maybeExportDeclar.splitExportDeclaration();
}
maybeConvertFromClassFunctionDeclaration(path) {
return path;
}
maybeConvertFromClassFunctionExpression(path) {
return path;
}
rename() {
const {
binding,
oldName,
newName
} = this;
const {
scope,
path
} = binding;
const parentDeclar = path.find(path => path.isDeclaration() || path.isFunctionExpression() || path.isClassExpression());
if (parentDeclar) {
const bindingIds = parentDeclar.getOuterBindingIdentifiers();
if (bindingIds[oldName] === binding.identifier) {
this.maybeConvertFromExportDeclaration(parentDeclar);
}
}
const blockToTraverse = arguments[0] || scope.block;
const skipKeys = {
discriminant: true
};
if (t.isMethod(blockToTraverse)) {
if (blockToTraverse.computed) {
skipKeys.key = true;
}
if (!t.isObjectMethod(blockToTraverse)) {
skipKeys.decorators = true;
}
}
(0, _traverseNode.traverseNode)(blockToTraverse, (0, _visitors.explode)(renameVisitor), scope, this, scope.path, skipKeys);
if (!arguments[0]) {
scope.removeOwnBinding(oldName);
scope.bindings[newName] = binding;
this.binding.identifier.name = newName;
}
if (parentDeclar) {
this.maybeConvertFromClassFunctionDeclaration(path);
this.maybeConvertFromClassFunctionExpression(path);
}
}
}
exports.default = Renamer;
//# sourceMappingURL=renamer.js.map
File diff suppressed because one or more lines are too long
+66
View File
@@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = traverseForScope;
var _t = require("@babel/types");
var _index = require("../index.js");
var _visitors = require("../visitors.js");
var _context = require("../path/context.js");
const {
VISITOR_KEYS
} = _t;
function traverseForScope(path, visitors, state) {
const exploded = (0, _visitors.explode)(visitors);
if (exploded.enter || exploded.exit) {
throw new Error("Should not be used with enter/exit visitors.");
}
_traverse(path.parentPath, path.parent, path.node, path.container, path.key, path.listKey, path.hub, path);
function _traverse(parentPath, parent, node, container, key, listKey, hub, inPath) {
if (!node) {
return;
}
const path = inPath || _index.NodePath.get({
hub,
parentPath,
parent,
container,
listKey,
key
});
_context._forceSetScope.call(path);
const visitor = exploded[node.type];
if (visitor != null && visitor.enter) {
for (const visit of visitor.enter) {
visit.call(state, path, state);
}
}
if (path.shouldSkip) {
return;
}
const keys = VISITOR_KEYS[node.type];
if (!(keys != null && keys.length)) {
return;
}
for (const key of keys) {
const prop = node[key];
if (!prop) continue;
if (Array.isArray(prop)) {
for (let i = 0; i < prop.length; i++) {
const value = prop[i];
_traverse(path, node, value, prop, i, key);
}
} else {
_traverse(path, node, prop, node, key, null);
}
}
if (visitor != null && visitor.exit) {
for (const visit of visitor.exit) {
visit.call(state, path, state);
}
}
}
}
//# sourceMappingURL=traverseForScope.js.map
@@ -0,0 +1 @@
{"version":3,"names":["_t","require","_index","_visitors","_context","VISITOR_KEYS","traverseForScope","path","visitors","state","exploded","explode","enter","exit","Error","_traverse","parentPath","parent","node","container","key","listKey","hub","inPath","NodePath","get","_forceSetScope","call","visitor","type","visit","shouldSkip","keys","length","prop","Array","isArray","i","value"],"sources":["../../src/scope/traverseForScope.ts"],"sourcesContent":["import { VISITOR_KEYS } from \"@babel/types\";\nimport type * as t from \"@babel/types\";\nimport type { HubInterface, Visitor } from \"../index.ts\";\nimport { NodePath } from \"../index.ts\";\nimport { explode } from \"../visitors.ts\";\nimport { _forceSetScope } from \"../path/context.ts\";\n\nexport default function traverseForScope(\n path: NodePath,\n visitors: Visitor,\n state: any,\n) {\n const exploded = explode(visitors);\n\n if (exploded.enter || exploded.exit) {\n throw new Error(\"Should not be used with enter/exit visitors.\");\n }\n\n _traverse(\n path.parentPath,\n path.parent,\n path.node,\n path.container!,\n path.key!,\n path.listKey,\n path.hub,\n path,\n );\n\n function _traverse(\n parentPath: NodePath,\n parent: t.Node,\n node: t.Node,\n container: t.Node | t.Node[],\n key: string | number,\n listKey: string | null | undefined,\n hub?: HubInterface,\n inPath?: NodePath,\n ) {\n if (!node) {\n return;\n }\n\n const path =\n inPath ||\n NodePath.get({\n hub,\n parentPath,\n parent,\n container,\n listKey,\n key,\n });\n\n _forceSetScope.call(path);\n\n const visitor = exploded[node.type];\n if (visitor?.enter) {\n for (const visit of visitor.enter) {\n visit.call(state, path, state);\n }\n }\n\n if (path.shouldSkip) {\n return;\n }\n\n const keys = VISITOR_KEYS[node.type];\n if (!keys?.length) {\n return;\n }\n\n for (const key of keys) {\n // @ts-expect-error key must present in node\n const prop = node[key];\n if (!prop) continue;\n if (Array.isArray(prop)) {\n for (let i = 0; i < prop.length; i++) {\n const value = prop[i];\n _traverse(path, node, value, prop, i, key);\n }\n } else {\n _traverse(path, node, prop, node, key, null);\n }\n }\n\n if (visitor?.exit) {\n for (const visit of visitor.exit) {\n visit.call(state, path, state);\n }\n }\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,EAAA,GAAAC,OAAA;AAGA,IAAAC,MAAA,GAAAD,OAAA;AACA,IAAAE,SAAA,GAAAF,OAAA;AACA,IAAAG,QAAA,GAAAH,OAAA;AAAoD;EAL3CI;AAAY,IAAAL,EAAA;AAON,SAASM,gBAAgBA,CACtCC,IAAc,EACdC,QAAiB,EACjBC,KAAU,EACV;EACA,MAAMC,QAAQ,GAAG,IAAAC,iBAAO,EAACH,QAAQ,CAAC;EAElC,IAAIE,QAAQ,CAACE,KAAK,IAAIF,QAAQ,CAACG,IAAI,EAAE;IACnC,MAAM,IAAIC,KAAK,CAAC,8CAA8C,CAAC;EACjE;EAEAC,SAAS,CACPR,IAAI,CAACS,UAAU,EACfT,IAAI,CAACU,MAAM,EACXV,IAAI,CAACW,IAAI,EACTX,IAAI,CAACY,SAAS,EACdZ,IAAI,CAACa,GAAG,EACRb,IAAI,CAACc,OAAO,EACZd,IAAI,CAACe,GAAG,EACRf,IACF,CAAC;EAED,SAASQ,SAASA,CAChBC,UAAoB,EACpBC,MAAc,EACdC,IAAY,EACZC,SAA4B,EAC5BC,GAAoB,EACpBC,OAAkC,EAClCC,GAAkB,EAClBC,MAAiB,EACjB;IACA,IAAI,CAACL,IAAI,EAAE;MACT;IACF;IAEA,MAAMX,IAAI,GACRgB,MAAM,IACNC,eAAQ,CAACC,GAAG,CAAC;MACXH,GAAG;MACHN,UAAU;MACVC,MAAM;MACNE,SAAS;MACTE,OAAO;MACPD;IACF,CAAC,CAAC;IAEJM,uBAAc,CAACC,IAAI,CAACpB,IAAI,CAAC;IAEzB,MAAMqB,OAAO,GAAGlB,QAAQ,CAACQ,IAAI,CAACW,IAAI,CAAC;IACnC,IAAID,OAAO,YAAPA,OAAO,CAAEhB,KAAK,EAAE;MAClB,KAAK,MAAMkB,KAAK,IAAIF,OAAO,CAAChB,KAAK,EAAE;QACjCkB,KAAK,CAACH,IAAI,CAAClB,KAAK,EAAEF,IAAI,EAAEE,KAAK,CAAC;MAChC;IACF;IAEA,IAAIF,IAAI,CAACwB,UAAU,EAAE;MACnB;IACF;IAEA,MAAMC,IAAI,GAAG3B,YAAY,CAACa,IAAI,CAACW,IAAI,CAAC;IACpC,IAAI,EAACG,IAAI,YAAJA,IAAI,CAAEC,MAAM,GAAE;MACjB;IACF;IAEA,KAAK,MAAMb,GAAG,IAAIY,IAAI,EAAE;MAEtB,MAAME,IAAI,GAAGhB,IAAI,CAACE,GAAG,CAAC;MACtB,IAAI,CAACc,IAAI,EAAE;MACX,IAAIC,KAAK,CAACC,OAAO,CAACF,IAAI,CAAC,EAAE;QACvB,KAAK,IAAIG,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGH,IAAI,CAACD,MAAM,EAAEI,CAAC,EAAE,EAAE;UACpC,MAAMC,KAAK,GAAGJ,IAAI,CAACG,CAAC,CAAC;UACrBtB,SAAS,CAACR,IAAI,EAAEW,IAAI,EAAEoB,KAAK,EAAEJ,IAAI,EAAEG,CAAC,EAAEjB,GAAG,CAAC;QAC5C;MACF,CAAC,MAAM;QACLL,SAAS,CAACR,IAAI,EAAEW,IAAI,EAAEgB,IAAI,EAAEhB,IAAI,EAAEE,GAAG,EAAE,IAAI,CAAC;MAC9C;IACF;IAEA,IAAIQ,OAAO,YAAPA,OAAO,CAAEf,IAAI,EAAE;MACjB,KAAK,MAAMiB,KAAK,IAAIF,OAAO,CAACf,IAAI,EAAE;QAChCiB,KAAK,CAACH,IAAI,CAAClB,KAAK,EAAEF,IAAI,EAAEE,KAAK,CAAC;MAChC;IACF;EACF;AACF","ignoreList":[]}