📦 添加虚拟环境和启动脚本

新增:
- backend/venv/ - Python 虚拟环境
- backend/start.sh - 启动脚本(使用虚拟环境)
- backend/requirements.txt - 依赖列表
- .gitignore - 忽略虚拟环境和缓存文件

说明:
- 每个项目使用独立虚拟环境
- 避免依赖冲突
- 启动脚本自动创建和激活虚拟环境
This commit is contained in:
2026-04-04 18:28:31 +08:00
parent 9ab279e1fe
commit 96f6318101
32058 changed files with 3949495 additions and 22 deletions

View File

@@ -0,0 +1,5 @@
const { plugin } = require("./plugin.cjs");
module.exports = function (options = {}) {
return (Parser) => plugin(options, Parser, (Parser.acorn || require("acorn")).tokTypes);
};

View File

@@ -0,0 +1,9 @@
import { Parser } from "acorn";
interface Options {
source?: boolean;
defer?: boolean;
}
declare function acornImportPhases(options?: Options): (BaseParser: typeof Parser) => typeof Parser;
export = acornImportPhases;

View File

@@ -0,0 +1,8 @@
import { Parser } from "acorn";
interface Options {
source?: boolean;
defer?: boolean;
}
export default function acornImportPhases(options?: Options): (BaseParser: typeof Parser) => typeof Parser;

View File

@@ -0,0 +1,6 @@
import { tokTypes } from "acorn";
import { plugin } from "./plugin.cjs";
export default function (options = {}) {
return Parser => plugin(options, Parser, Parser.acorn ? Parser.acorn.tokTypes : tokTypes);
}

View File

@@ -0,0 +1,125 @@
/**
* @param {{ defer?: boolean, source?: boolean }} options
* @param {typeof import("acorn").Parser} Parser
* @param {typeof import("acorn").tokTypes} acorn
*/
exports.plugin = function acornImportPhase(options, Parser, tt) {
return class extends Parser {
parseImport(node) {
this._phase = null;
const result = super.parseImport(node);
if (this._phase) {
node.phase = this._phase;
}
return result;
}
parseImportSpecifiers() {
let phase =
options.defer !== false && this.isContextual("defer")
? "defer"
: options.source !== false && this.isContextual("source")
? "source"
: null;
if (!phase) return super.parseImportSpecifiers();
const phaseId = this.parseIdent();
if (this.isContextual("from") || this.type === tt.comma) {
const defaultSpecifier = this.startNodeAt(phaseId.start, phaseId.loc && phaseId.loc.start);
defaultSpecifier.local = phaseId;
this.checkLValSimple(phaseId, /* BIND_LEXICAL */ 2);
const nodes = [this.finishNode(defaultSpecifier, "ImportDefaultSpecifier")];
if (this.eat(tt.comma)) {
if (this.type !== tt.star && this.type !== tt.braceL) {
this.unexpected();
}
nodes.push(...super.parseImportSpecifiers());
}
return nodes;
}
this._phase = phase;
if (phase === "defer") {
if (this.type !== tt.star) {
this.raiseRecoverable(
phaseId.start,
"'import defer' can only be used with namespace imports ('import defer * as identifierName from ...')."
);
}
} else if (phase === "source") {
if (this.type !== tt.name) {
this.raiseRecoverable(
phaseId.start,
"'import source' can only be used with direct identifier specifier imports."
);
}
}
const specifiers = super.parseImportSpecifiers();
if (phase === "source" && specifiers.some(s => s.type !== "ImportDefaultSpecifier")) {
this.raiseRecoverable(
phaseId.start,
`'import source' can only be used with direct identifier specifier imports ('import source identifierName from ...').`
);
}
return specifiers;
}
parseExprImport(forNew) {
const node = super.parseExprImport(forNew);
if (node.type === "MetaProperty" && (node.property.name === "defer" || node.property.name === "source")) {
if (this.type === tt.parenL) {
const dynImport = this.parseDynamicImport(this.startNodeAt(node.start, node.loc && node.loc.start));
dynImport.phase = node.property.name;
return dynImport;
} else {
this.raiseRecoverable(
node.start,
`'import.${node.property.name}' can only be used in a dynamic import.`
);
}
}
return node;
}
parseImportMeta(node) {
this.next();
var containsEsc = this.containsEsc;
node.property = this.parseIdent(true);
const { name } = node.property;
if (name !== "meta" && name !== "defer" && name !== "source") {
this.raiseRecoverable(
node.property.start,
"The only valid meta property for import is 'import.meta'"
);
}
if (containsEsc) {
this.raiseRecoverable(
node.start,
`'import.${name}' must not contain escaped characters`
);
}
if (
name === "meta" &&
this.options.sourceType !== "module" &&
!this.options.allowImportExportEverywhere
) {
this.raiseRecoverable(
node.start,
"Cannot use 'import.meta' outside a module"
);
}
return this.finishNode(node, "MetaProperty");
}
};
};