@code-recycle/cli
Version:
高级语法查询替换工具;Advanced syntax query replacement tool
1,379 lines (1,251 loc) • 55.3 kB
TypeScript
/// <reference types="node" />
import { default as __2 } from 'lodash';
import { basename } from '@angular-devkit/core';
import { dirname } from '@angular-devkit/core';
import { firstValueFrom } from 'rxjs';
import { getSystemPath } from '@angular-devkit/core';
import { InjectionToken } from 'static-injector';
import { Injector } from 'static-injector';
import { isAbsolute } from '@angular-devkit/core';
import { join } from '@angular-devkit/core';
import { normalize } from '@angular-devkit/core';
import { Observable } from 'rxjs';
import { Path } from '@angular-devkit/core';
import { Pattern } from 'fast-glob';
import { relative } from '@angular-devkit/core';
import { resolve } from '@angular-devkit/core';
import { split } from '@angular-devkit/core';
import { virtualFs } from '@angular-devkit/core';
export declare function arrayBufferToText(buffer: ArrayBuffer, path?: string): string;
declare class ASTViewNode<NODE> implements CommonNode<NODE> {
#private;
index: number;
/** 节点类型 */
type: ASTViewNodeType;
/** 内容 */
value: string;
/** 位置 */
range: NodeRange;
/** 额外数据 */
private extraFn;
context: {
map: Map<string, (origin?: boolean) => any>;
node: NODE;
};
/** 标签 */
tag?: string;
private options?;
infer: InferData<NODE>;
parent?: ASTViewNode<NODE>;
clone(): ASTViewNode<NODE>;
/** 只在上下文存在,没有上下文正常 */
toJSON?: () => {};
get contentRange(): NodeRange;
constructor(index: number,
/** 节点类型 */
type: ASTViewNodeType,
/** 内容 */
value: string,
/** 位置 */
range: NodeRange,
/** @internal */
childrenFn: () => ASTViewNode<NODE>[],
/** 额外数据 */
extraFn: () => Record<string, ExtraDataItem>, context: {
map: Map<string, (origin?: boolean) => any>;
node: NODE;
},
/** 标签 */
tag?: string, options?: TreeOptions);
/** 子元素 */
get children(): ASTViewNode<NODE>[];
get extra(): Record<string, ExtraDataItem>;
}
/** node是普通类型 token是最后的元素 */
declare type ASTViewNodeType = 'node' | 'token';
export declare type AutoDATA<INPUT extends any[], RETURN = string> = ((...contextArgs: INPUT) => Promise<RETURN>) | ((...contextArgs: INPUT) => RETURN) | RETURN | Promise<RETURN>;
export declare function autoDataRunner<INPUT extends any[], RETURN>(data: AutoDATA<INPUT, RETURN>, input: INPUT): Promise<RETURN>;
declare interface BaseOptions {
toJsonWithChildren?: boolean;
toJsonWithExtra?: boolean;
}
export declare function bufferEqual(a: ArrayBuffer, b: ArrayBuffer): boolean;
declare type CallBackReturn = (Partial<ContentResolveItem> | CUSTOM_CHANGE | undefined)[] | undefined | Promise<(Partial<ContentResolveItem> | CUSTOM_CHANGE | undefined)[]> | void | Partial<ContentResolveItem> | CUSTOM_CHANGE;
export declare function codeRecycleByNode(path: string, root?: string, options?: Partial<CoreOptions>): Promise<(<T>(Instance: ScriptFunction<T>) => Promise<T>)>;
/** 外部暴露这个,但是允许手动变更成其他的 */
declare interface CommonNode<NODE_TYPE, VALUE = string> {
type: string;
value: VALUE;
range: NodeRange;
infer: InferData<NODE_TYPE>;
children: CommonNode<NODE_TYPE, VALUE>[];
}
export declare function completePromise(input: Observable<void>): Promise<unknown>;
declare class ComposedNode<T> implements CommonNode<T> {
item: LikeMatchItem<T>;
range: NodeRange;
value: string;
infer: InferData<T>;
static create<T>(item: LikeMatchItem<T>, fileContent: string): ComposedNode<T>;
readonly type = "composed";
children: CommonNode<T, string>[];
constructor(item: LikeMatchItem<T>, range: NodeRange, value: string, infer: InferData<T>);
}
export declare function condition(value: any | Statement, trueInput: Statement | string, falseInput: Statement | string): (context: QueryContext) => string;
/**
* @group 配置
*/
export declare interface Config {
debug?: boolean | Record<keyof typeof DEBUG_OPTION, boolean>;
/** 演练模式,修改内容输出到控制台 */
dryRun?: boolean;
/** git clone 的远程仓库放到哪里.默认为系统临时文件夹 */
gitCloneTmpDir?: string;
/** 执行撤销模板时,相同文件是否需要确认(编辑器) */
revokeSameConfirm?: boolean;
get?: (name: string) => Promise<any>;
/** antlr4 解析器位置,使用 download/dir 需要指定;使用编辑器时默认下载到拓展文件夹内 */
antlrParserDir?: string;
/** tree-sitter 解析器位置,使用 download/dir 需要指定;使用编辑器时默认下载到拓展文件夹内 */
treeSitterParserDir?: string;
/** 使用不同的包管理工具,默认为 npm */
packageManager?: PackageManager;
/** 解析器下载方式, cli默认为 package(npm),编辑器为 download */
parserDownload?: 'package' | 'download' | 'dir';
/** 下载额外依赖时指定的 npm 仓库镜像位置 */
registryList?: string[];
/** @ignore */
disableDebugDate?: boolean;
/** 指定拓展名对应解析器; `code-recycle parserList` 查看解析器; `code-recycle extnameList` 查看默认拓展名对应解析器*/
parserMap?: Record<string, {
use: string;
language: string;
}>;
/** 一些默认行为修改 */
default?: {
/** 节点查询 */
nodeQueryOption: DefaultNodeQueryOption;
/** 模板策略 */
templateStrategy: ConflictStrategy;
/** 文件查询 */
fileQueryLayer: Pick<FileCopyLayer, 'ignoreList' | 'excludeList'>;
};
}
/** 一些配置 */
export declare const ConfigToken: InjectionToken<Config>;
/** @group 配置 */
export declare interface ConflictStrategy {
/**
* 存在文件冲突时的操作
*
* error: 抛出异常
*
* default: 不改变
*
* override: 覆盖当前文件
*
* editor: 编辑器处理(需要编辑器支持)
*
*/
conflict?: 'error' | 'default' | 'override' | 'editor' | (string & {});
/** {@inheritDoc ConflictStrategy.conflict} */
binaryConflict?: 'error' | 'default' | 'override' | (string & {});
/**
* 撤销时产生冲突时的操作(当前文件与撤销文件不同时)
*
* delete: 直接删除
*
* retain: 保留文件
*
* editor: 编辑器处理(需要编辑器支持)
*
*/
revokeConflict?: 'delete' | 'retain' | 'editor' | (string & {});
/** {@inheritDoc ConflictStrategy.revokeConflict} */
binaryRevokeConflict?: 'delete' | 'retain' | (string & {});
}
export declare interface ContentResolveItem extends ResolveItemBase {
/** 文件内容 */
content: string;
/** 文件路径 */
path?: string;
/** 查询到的文件节点 */
node?: CommonNode<any>;
readonly originNode?: CommonNode<any>;
readonly id: string;
readonly languageConfig: LanguageOption;
}
declare class ContentResolveUpdate implements ContentResolveItem {
#private;
content: string;
private parserService;
languageConfig: LanguageOption;
path?: string | undefined;
resolve$$: Observable<CssSelectorBase<any>>;
private resolveCache$$;
node?: CommonNode<any>;
readonly id: string;
constructor(content: string, parserService: ParserService, languageConfig: LanguageOption, path?: string | undefined);
refresh(content: string): void;
cloneNode(node: CommonNode<any>): this;
get originNode(): CommonNode<any, string> | undefined;
toJSON(): {
node: CommonNode<any, string> | undefined;
content: string;
path: string | undefined;
resolve$$: string;
position: {
line: number;
column: number;
}[] | undefined;
};
}
export declare type CopyFormItem = string | {
url: string;
match?: string[] | string;
output?: string;
type?: 'branch' | 'tag' | 'commit';
commit?: string;
};
export declare interface CoreOptions {
path: string;
/** 默认cwd */
workspacePath?: string;
vfs: virtualFs.Host;
hint: Hint;
documentContext?: DocumentContext;
globalContext?: GlobalContext;
config: Partial<Config>;
platform?: Platform;
scriptCwd: string;
}
/** 核心 */
export declare const CoreOptionsToken: InjectionToken<ResolvedCoreOptions>;
/**
* 通用节点模式,所有节点的数据结构相同
* 保护类型为语言需要实现的,astTree调用
*/
declare abstract class CssSelectorBase<NODE extends object> {
#private;
private baseOptions?;
abstract readonly rootNodeList: NODE[];
/** 可选 */
protected abstract content: string;
constructor(baseOptions?: BaseOptions);
protected abstract getNodePosition(node: NODE): NodeRange;
protected abstract findTagName(node: NODE): string | undefined;
/** 用于通用节点的使用 */
protected abstract getChildren(node: NODE): NODE[];
get nodeList(): ASTViewNode<NODE>[];
queryAll(node: ASTViewNode<NODE>, selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>[];
queryAll(selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>[];
queryOne(node: ASTViewNode<NODE>, selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>;
queryOne(selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>;
match(node: ASTViewNode<NODE>, content: string, options?: LikeMatchOptions): ComposedNode<NODE>[];
match(content: string, options?: LikeMatchOptions): ComposedNode<NODE>[];
locate(position: NodeRange): {
node: ASTViewNode<NODE>;
pathList: number[];
}[];
protected getNodeExtraData(node: NODE, callPath: string, registryMap: Map<string, () => any>, filterList?: string[]): Record<string, ExtraDataItem>;
getAstTree(nodeList?: NODE[], hasChildren?: boolean | number, options?: TreeOptions): {
children: ASTViewNode<NODE>[];
callbackMap: Map<string, () => any>;
};
protected registryMethod(root: string, name: string, fn: () => any, map: Map<string, () => void>): ExtraDataCallItem;
/** 引用数据 */
protected registryRefData(root: string, name: string, fn: (origin?: boolean) => any, map: Map<string, (origin?: boolean) => void>): ExtraDataRefItem;
}
/** 当前调用处于哪个文件夹 */
export declare const CurrentDirToken: InjectionToken<Path>;
export declare const CurrentPathToken: InjectionToken<Path>;
declare type CUSTOM_CHANGE = {
value: string;
range: NumberTuple2;
};
export declare function data(str: string): (context: QueryContext) => string;
/** @group 配置 */
declare const DEBUG_OPTION: {
parser: string;
installParser: string;
};
/** @group 配置 */
export declare type DefaultNodeQueryOption = Pick<NodeQueryOption, 'delete' | 'multi' | 'nullable' | 'optional' | 'mode' | 'insertBefore' | 'insertAfter'>;
export declare function deleteImport(name: string): NodeQueryOption;
/** 从编辑器中传入的值 */
export declare interface DocumentContext {
/** 编辑器选中/代码片段调用 */
insertRange?: {
value: string;
range: NumberTuple2;
}[];
/** 代码片段调用 */
selectRange?: {
value: string;
range: NumberTuple2;
}[];
path: Path;
dir: Path;
workspacePath: Path;
/** 代码片段 */
snippetParameters?: Record<string, any>;
/** 代码片段 */
trigger?: string;
}
/** 文档,可选 */
export declare const DocumentContextToken: InjectionToken<DocumentContext>;
declare type EachFunction<T> = (node: ASTViewNode<T>, infer: InferData<T>) => boolean | undefined | void | ASTViewNode<T>[] | ASTViewNode<T>;
declare class ExtraDataCallItem {
value: string;
readonly type = "Call";
constructor(value: string);
}
declare type ExtraDataItem = ExtraDataLiteralItem | ExtraDataCallItem | ExtraDataRefItem;
declare class ExtraDataLiteralItem {
value: string | number | boolean | Record<string, any> | undefined;
readonly type = "Literal";
constructor(value: string | number | boolean | Record<string, any> | undefined);
}
/** 可能是节点 */
declare class ExtraDataRefItem {
value: string;
readonly type = "Node";
constructor(value: string);
}
export declare function fileBufferToString(fileBuffer: ArrayBuffer): string;
export declare function fileContent(str: string): (context: QueryContext) => string;
/**
* @group 文件查询
*/
export declare type FileCopyLayer = {
type: 'copy';
/** 默认为本地文件,允许使用git拉取远程仓库 */
source?: 'local' | 'git';
/** 文件夹或路径(列表);使用git时可以配置拉取文件,排除文件,分支 */
from: AutoDATA<[context: QueryContext], CopyFormItem | undefined> | AutoDATA<[context: QueryContext], CopyFormItem | undefined>[];
/** 排除路径 */
excludeList?: string[];
/** 忽略文件
*
* 比如.gitignore
*/
ignoreList?: string[];
/** 文件夹或路径 */
to: AutoDATA<[context: QueryContext], string>;
disable?: AutoDATA<[context: QueryContext], boolean>;
} & TemplateOption & {
strategy?: ConflictStrategy;
};
/**
* @group 文件查询
*/
export declare interface FileCreateLayer {
type: 'create';
/** 文件名 */
path: AutoDATA<[context: QueryContext], string | undefined>;
/** 内容 */
content: AutoDATA<[context: QueryContext], string>;
/** 禁用此层 */
disable?: AutoDATA<[context: QueryContext], boolean>;
}
/**
* @group 文件查询
*
*/
export declare interface FileQueryCommon {
path?: AutoDATA<[context: QueryContext], string>;
/** 以内容创建解析器 */
content?: AutoDATA<[context: QueryContext], string>;
/** 默认为ts解析器 */
parser?: {
use: string;
language: string;
};
glob?: boolean;
/** 创建新文件时查询节点内容作为解析内容 */
query?: string;
disable?: AutoDATA<[context: QueryContext], boolean>;
}
/**
* @group 文件查询
*/
export declare interface FileQueryLayer extends FileQueryCommon {
/** 不指定类型时默认为 query */
type?: 'query';
/** 文件路径;与 content 互斥 */
path?: AutoDATA<[context: QueryContext], string>;
/** 以内容创建解析器;与 path 互斥 */
content?: AutoDATA<[context: QueryContext], string>;
/** 链式查询节点 */
list: NodeQueryFlowList;
/** 根据后缀自动判断解析器类型,允许显式指定 */
parser?: {
use: string;
language: string;
};
/** 开启后 path 为 pattern;[帮助](https://github.com/micromatch/picomatch?tab=readme-ov-file#basic-globbing) */
glob?: boolean;
/** 创建新文件时查询节点内容作为解析内容 */
query?: string;
/**
* ? 不确定此设计是否合理
* 将查询/替换结果直接更新,使用 query(如果存在)查询到的内容写入到此文件中 */
newPath?: string;
/** 命名之后,可以使用`root.xx`访问该层上下文,如果该层有多个文件,那么获得的是一个主上下文,使用xx[index]访问真实文件上下文 */
name?: string;
/** 是否将替换结果直接更新到文件中 */
update?: boolean;
/** 禁用此层 */
disable?: AutoDATA<[context: QueryContext], boolean>;
}
/**
* @group 文件查询
*
*/
export declare type FileQueryList = (FileQueryLayer | FileCreateLayer | FileCopyLayer)[];
/** 函数上下文,可选 */
export declare const FunctionParametersToken: InjectionToken<Record<string, (arg: any) => Promise<any>>>;
/** 如果是原始值,那么就是原始值,否则会调用上下文 */
export declare function getData<T = string>(data: Statement<T> | T, context: QueryContext): T;
export declare function getStatementValue<T = string>(input: AutoDATA<[context: QueryContext], T>, context: QueryContext): Promise<T>;
export declare function gitCloneRepoName(options: {
url: string;
commit: string | undefined;
type: string | undefined;
match: string | string[] | undefined;
}): string;
export declare interface GlobalContext {
setBoolean: (list: InputInfo[]) => Promise<Record<string, boolean>>;
setInput: (list: InputInfo[]) => Promise<Record<string, string>>;
}
export declare const GlobalInputToken: InjectionToken<GlobalContext>;
export declare type GridList = GridType[] | GridType[][];
export declare interface GridType {
fixed?: boolean;
cols?: number;
config: Record<string, any>;
}
export declare interface Hint {
dialogInfo(message: string, options: any): Promise<void>;
outputLog(...list: any[]): Promise<any>;
outputWarn(...list: any[]): Promise<any>;
outputError(...list: any[]): Promise<any>;
debug(...list: any[]): void;
}
/** 提示 */
export declare const HintToken: InjectionToken<Hint>;
export declare type ImportInfo = {
type?: boolean;
path: string;
importList: string[];
default?: boolean;
};
export declare function ImportNode(node: ContentResolveItem, importList: string | ImportInfo[], prefix?: 'import' | 'export'): ContentResolveItem;
export declare type ImportOrExportInfo2 = {
type?: boolean;
path?: string;
newPath?: string;
importList?: (string | {
name: string;
as?: string;
newName?: string;
newAs?: string;
})[];
default?: boolean;
delete?: boolean;
};
export declare function importText(importList: ImportInfo[], prefix?: 'import' | 'export'): string;
export declare function includeValue(list: string[], map?: (item: string) => string): () => string;
export declare function incrementalChange(oldChange: string, newChange: string, start: number): ({
readonly start: number;
readonly content: string;
readonly type: 1;
readonly length?: undefined;
} | {
readonly start: number;
readonly length: number;
readonly type: -1;
readonly content?: undefined;
})[];
declare type InferData<T> = Record<string, ASTViewNode<T> | ASTViewNode<T>[]>;
export { Injector }
export declare interface InputInfo {
name: string;
message?: string;
force?: boolean;
}
export declare function isInWorkspace(root: Path, filePath: Path): boolean;
export declare function isObject(obj: unknown): obj is Object;
export declare function isPlainText(buffer: Uint8Array | ArrayBuffer): Promise<boolean>;
export declare interface LanguageOption {
use: string;
language: string;
extraOptions?: any;
}
declare type LikeMatchItem<T> = {
pathList: ASTViewNode<T>[];
matchedCountList: number[];
infer: InferData<T>;
last: ASTViewNode<T>;
next?: ASTViewNode<T>;
};
declare type LikeMatchLevel = 'all' | 'top' | 'bottom';
declare interface LikeMatchOptions {
count?: number;
matchLevel?: LikeMatchLevel;
}
export declare const mayBeVar = ":is(VariableDeclaration>Identifier,BindingElement>ColonToken+*,PropertyAccessExpression::children(0),CallExpression>SyntaxList>Identifier,BinaryExpression>Identifier,ConditionalExpression>Identifier,PropertyAssignment>ColonToken+Identifier,CallExpression>Identifier,ParenthesizedExpression>OpenParenToken+Identifier)";
export declare function methodRename(name: string, replace: string, options?: Partial<NodeQueryOption>): NodeQueryOption;
export declare const nextPromise: typeof firstValueFrom;
/**
* @group 文件查询
*
*/
export declare type NodeQueryFlowList = (NodeQueryItem | NodeQueryItem[])[];
/**
* @group 文件查询
*
*
*/
export declare type NodeQueryItem = NodeQueryOption | {
/** 全部有查询结果 */
allOf: NodeQueryItem[];
} | {
/** 有且只有一个有查询结果 */
oneOf: NodeQueryItem[];
} | {
/** 任意一个有查询结果,不会再查询后面的兄弟选项 */
anyOf: NodeQueryItem[];
} | {
/** 不能有查询结果 */
not: NodeQueryItem;
};
/**
* @group 文件查询
*
*/
export declare interface NodeQueryOption {
disable?: AutoDATA<[context: QueryContext], boolean>;
/**
* 用于上下文匹配
* 当使用 multi 时,需要指定 name[x] 匹配到指定选项,
*/
name?: string;
/** 根据查询模式不同使用不同语法 */
query?: AutoDATA<[context: QueryContext], string>;
/** 查询模式. selector: css选择器 like: 相似模式 */
mode?: QueryMode;
/** 模式的一些选项,目前用于like */
modeOptions?: {
matchLevel?: 'all' | 'top' | 'bottom';
};
/** true:返回多个结果列表,false:只有一个结果 */
multi?: boolean;
/** 使用当前查询结果作为父节点进行下一步查询 */
children?: NodeQueryFlowList;
/** 直接替换时,表示替换当前匹配节点,使用对象替换时表示替换查询中匹配到的变量 */
replace?: AutoDATA<[context: QueryContext], string> | Record<string, AutoDATA<[context: QueryContext, node: CommonNode<any>], string | {
value: string;
range?: NumberTuple2;
}>>;
/** 删除节点 */
delete?: boolean;
/** 插入到节点前面 */
insertBefore?: boolean;
/** 插入到节点后面 */
insertAfter?: boolean;
/** 可选,当查询不到时不会报错;使用 oneOf/anyOf/not 时强制为 true */
optional?: boolean;
/**
*
* 替换节点时处理节点范围 */
offset?: AutoDATA<[context: QueryContext], [number, number]>;
/** 返回一个范围,替换query */
range?: AutoDATA<[context: QueryContext, range?: [number, number]], [number, number] | undefined>;
/** 查询到节点时使用 */
callback?: (context: QueryContext, index: number) => CallBackReturn;
/** multi:true 时,列表回调 */
listCallback?: (contextList: QueryContext[], self: QueryContext) => CallBackReturn;
/**
* 查询时使用其他节点作为父节点,仅上下文中查询父节点变化
*/
parentMap?: AutoDATA<[context: QueryContext], ParentMap>;
/** 返回一个列表,替换当前节点循环进行查询 */
loop?: (context: QueryContext, index: number) => ContentResolveItem[] | boolean;
/** 用于异常提示 */
description?: string;
/**
* 未查询到数据时是否可以继续
* 子级节点应该使用 parentMap 获得新的父节点进行查询
*/
nullable?: boolean;
}
declare type NodeRange = [number, number];
/**
* ! 仅限 selector 使用
* @param str 路径
* @param contentRange 内容
* @returns
*/
export declare function nodeValue(str: string, contentRange?: boolean): (context: QueryContext) => string;
export declare function not(input: Statement): (context: QueryContext) => string;
/** 范围 */
export declare type NumberTuple2 = [number, number];
export declare function or(...args: (string | Statement)[]): (context: QueryContext) => string;
/** @group 配置 */
export declare type PackageManager = 'npm' | 'cnpm' | 'yarn' | 'pnpm' | (string & {});
export declare type ParentMap = string | QueryContext | ContentResolveItem | FileQueryCommon;
declare class ParserService {
#private;
constructor();
get parserMap$(): Map<string, RawLanguageItem>;
getParserInstance(filePath: string, content: string, options: BaseOptions, option: LanguageOption): Promise<CssSelectorBase<any>>;
getDefaultExtLanguageOptions(filePath: Path): {
use: string;
language: string;
}[] | undefined;
get parserList(): LanguageOption[];
}
export declare function parseYaml(content: string): any;
export { Path }
export declare type PathTemplateFn = (input: string, path: Path) => any;
declare type PipeObject = Record<string, (input: any, ...args: any[]) => any>;
/** @ignore */
export declare interface Platform {
applyFile?: (filePath: Path, templateBuffer: ArrayBuffer, originBuffer: ArrayBuffer, mergeStrategy: string, option: {
host: ReadScopedHost;
}) => Promise<boolean>;
revokeFile?: (filePath: Path, templateBuffer: ArrayBuffer, originBuffer: ArrayBuffer, mergeStrategy: string, option: {
host: ReadScopedHost;
}) => Promise<boolean>;
}
/** 平台,可选 */
export declare const PlatformToken: InjectionToken<Platform>;
export declare function proxyClone<T extends Record<string, any>>(obj: T, type?: Object): T;
export declare function queryCall(name: string): string;
/**
* @group 文件查询
*
**/
export declare class QueryContext {
#private;
parent?: QueryContext | undefined;
name?: string | number | undefined;
/** 子查询 */
children: QueryContext[];
data?: any;
/** 解析节点,带文件来源的 */
node?: ContentResolveItem;
/** 根上下文,可以查询到所有信息 */
root: QueryContext;
/** 当前查询文件项的文件上下文,节点查询选项中使用 parentMap 不会修改 file 属性 */
file: QueryContext;
/** 如果没有查询到内容会写入原因 */
unFindMessage?: string;
constructor(util: Util, node?: ContentResolveItem, parent?: QueryContext | undefined, name?: string | number | undefined);
create(node?: ContentResolveItem, name?: string | number): QueryContext;
get index(): number;
/**
* 用于上下文中手动调用管道
* 管道就是函数在模板上的应用
*/
get pipe(): Record<string, any>;
/**
* root 获得根上下文
* item 获得当前项上下文
* parent[1-?] 返回父级上下文
*/
getContext<OPT extends boolean = false>(path?: string | string[], optional?: OPT): OPT extends false ? QueryContext : QueryContext | undefined;
getNode<OPT extends boolean = false>(path?: string | string[], optional?: OPT): OPT extends false ? ContentResolveItem : ContentResolveItem | undefined;
getNodeValue<OPT extends boolean = false>(path?: string, optional?: OPT): OPT extends false ? string : string | undefined;
mark(message: string): void;
}
/** 变更导入 */
export declare function queryDeclaration(name: string, type: 'FunctionDeclaration' | 'TypeAliasDeclaration' | 'InterfaceDeclaration'): string;
export declare function queryImport(name: string): string;
export declare function queryImportInclude(name: string, list?: string[]): string;
export declare type QueryMode = 'selector' | 'like';
declare interface QueryOptions<T> {
eachFunction?: Record<string, EachFunction<T>>;
matchLevel?: LikeMatchLevel;
}
/** pipe对象 */
export declare type QueryPipe = PipeObject | Record<string, PipeObject>;
declare function queryStatement(str: string): (data?: Record<string, any>) => any;
/**
* ! 仅限 selector
*/
export declare function range(str: string, contentRange: boolean): (context: QueryContext) => [number, number];
export declare function raw(str: string | Statement): (context: QueryContext) => string;
declare interface RawLanguageItem {
use: string;
language: string;
parser: (fileName: string, content: string, baseOption: BaseOptions, extraOptions?: any) => Promise<CssSelectorBase<any>>;
extraOptions?: any;
}
declare class ReadCordHost extends virtualFs.CordHost {
private delegate;
hint?: Hint | undefined;
constructor(delegate: virtualFs.Host, hint?: Hint | undefined);
clear(): void;
writeToVFS(dryRun?: boolean): Promise<void>;
restore(filePath: Path): void;
}
export declare class ReadScopedHost extends virtualFs.ResolverHost<{}> {
#private;
private delegate;
path?: Path | undefined;
protected _resolve(path: Path): Path;
workspacePath?: Path;
constructor(delegate: ReadCordHost | virtualFs.Host, path?: Path | undefined);
listAll(searchDir: Path, options?: {
ignoreList?: string[];
excludeList?: string[];
}): Path[] | Promise<Path[]>;
/**
* todo 解码,目前默认是utf-8
*/
readContent(path: Path, options?: {
encoding: string;
}): Promise<string | undefined>;
/** 绝对路径 0 当前 -1 向里 1 向外,*/
queryFile(dir: Path, item: {
filePattern?: string;
queryMode: 0 | 1 | -1;
ignore?: Pattern[];
}, filter: (filePath: Path) => Promise<boolean>): Promise<Path[] | undefined>;
clear(): void;
writeToFs(dryRun?: boolean): Promise<void>;
restore(filePath: Path): void;
records(): virtualFs.CordHostRecord[];
/** 返回改路径对应的文件夹(如果是文件夹就直接返回) */
pathDir(path: Path): Promise<Path>;
}
export declare function renameImport(oldName: string, newName: string): NodeQueryOption;
/** @ignore */
export declare interface ResolvedCoreOptions extends CoreOptions {
/** 指定文件夹,相对位置 */
dir: Path;
/** 指定文件(文件夹) */
path: Path;
/** 根位置 */
workspacePath: Path;
/** 脚本位置/运行位置 */
scriptCwd: Path;
}
declare interface ResolveItemBase {
resolve$$: Observable<CssSelectorBase<any>>;
refresh: (content: string) => void;
cloneNode: (item: any) => ContentResolveItem;
}
export declare type RuleMap = RuleRunner['runnerCall'];
declare class RuleRunner {
#private;
injector: Injector;
/** 文件夹 */
host: ReadScopedHost;
extraRule: Record<string, Record<string, (...args: any) => any>>;
constructor();
runnerCall: {
call: {
/** 调用其他脚本,可以与源脚本格式不同 */
script: (filePath: string) => Promise<any>;
};
read: {
/** 通过 glob 匹配符合条件的文件创建解析器 */
fileResolveByPattern: <T extends boolean = false>(filePattern?: string, selector?: string, options?: {
ignore?: string[] | undefined;
queryMode?: 0 | 1 | -1 | undefined;
all: T;
languageOption?: LanguageOption | undefined;
}) => Promise<(T extends true ? ContentResolveItem[] : ContentResolveItem) | undefined>;
/** 根据文件路径/文件路径列表创建文件解析器 */
fileResolve: <T_1 extends string | string[]>(filePath: T_1, languageOption?: LanguageOption) => Promise<T_1 extends string[] ? ContentResolveItem[] : ContentResolveItem>;
/** 根据文本创建解析器 */
contentResolve: (content: string, languageOption?: LanguageOption) => Promise<ContentResolveUpdate>;
/** 读取文件编辑器上的相关参数(限编辑器支持) */
editorInput: (type: 'insertRange' | 'selectRange' | 'path' | 'workspacePath' | 'snippetParameters' | 'trigger' | 'dir') => Promise<string | Record<string, any> | Path | {
value: string;
range: NumberTuple2;
}[] | {
value: string;
range: NumberTuple2;
}[] | undefined>;
/** 将文件解析为:对象(json/yaml)/buffer/plaintxt */
parseToObject: (filePath: string, type: 'json' | 'plain' | 'buffer' | 'yaml') => Promise<any>;
/** 读取一些设置;需要平台传入 */
setting: (value: string) => Promise<any>;
};
query: {
/**
* 选择器查询模式
*
* 使用[CSS选择器查询](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors)
* @param contentResolve
* @param selector
* @param all
* @returns
*/
selector: <ALL extends boolean = false>(contentResolve: ContentResolveItem, selector: string, all?: ALL, options?: QueryOptions<any>) => Promise<ALL extends true ? ContentResolveItem[] : ContentResolveItem | undefined>;
/**
* like 查询模式
* 与普通查询的语法几乎一样,但是更遵循语言的语法
* @param contentResolve
* @param selector
* @param count
* @returns
*/
like: <Count extends number>(contentResolve: ContentResolveItem, selector: string, count: Count, options?: LikeMatchOptions) => Promise<Count extends 1 ? ContentResolveItem | undefined : ContentResolveItem[]>;
};
resolve: {
queryStatement: typeof queryStatement;
};
operator: {
/**
* 替换文件的指定范围
* @param list
* @param fileMap 返回需要修改的文件
* @param rangeMap 返回需要修改的范围
* @param contentMap 返回需要修改的内容
* @returns
*/
replaceNode: <T_2>(list: T_2[], fileMap: (item: T_2) => ContentResolveItem | Promise<ContentResolveItem>, rangeMap: (item: T_2) => NumberTuple2 | Promise<NumberTuple2>, contentMap: (item: T_2) => string | Promise<string>) => Promise<void>;
/**
* 删除指定文件
* @param filePath
*/
deleteFile: (filePath: string) => Promise<void>;
/** 创建新文件 */
newFile: (fileName: string, content: string | Buffer) => Promise<void>;
/** 重命名文件 */
renameFile: (oldName: string, newName: string) => Promise<void>;
/** 插入代码片段;需要编辑器支持 */
insertSnippet: (input: string, position: NumberTuple2 | NumberTuple2[]) => Promise<never>;
template: (fromList: CopyFormItem[], to: string, source: "local" | "git" | undefined, excludeList?: string[] | undefined, ignoreList?: string[] | undefined, templateOption?: TemplateOption | undefined, revoke?: boolean | undefined, conflictStrategy?: ConflictStrategy | undefined) => Promise<void>;
/** 执行命令 */
commandExec: (command: string, args: string[], cwd?: string) => Promise<void>;
};
globalVariable: {
/**
* 交互设置 string
* @param input
* @returns
*/
setStringByInteractive: (input: {
name: string;
force?: boolean;
message?: string | undefined;
}[]) => Promise<{
[x: string]: any;
}>;
/** 交互设置 boolean */
setBooleanByInteractive: (input: {
name: string;
force?: boolean;
message?: string | undefined;
}[]) => Promise<{
[x: string]: any;
}>;
/**
* 设置全局变量
* @param key
* @param value
*/
set: (key: string, value: any) => Promise<void>;
/**
* 读取全局变量
* @param keyPath
* @returns
*/
get: (keyPath: string) => Promise<any>;
};
common: {
/** 读取对象数据,可以用来读取节点的 extra 部分 */
getData: (input: Record<string, any>, path: string | number) => Promise<any>;
/** 相似度判断,优先进行startsWith判断,再判断距离相似 */
didYouMean: (input: string, list: string[], options: {
threshold: number;
}) => Promise<string | null>;
/** 范围比较: input1 ? input2 */
rangeCompare: (input1: NumberTuple2, type: 'contains' | 'reverse-contains' | 'intersection' | 'equal' | 'not-intersection', input2: NumberTuple2) => Promise<boolean>;
};
view: {
/** 网格布局 */
grid: (config: {
list: GridList;
}) => Promise<{
type: string;
children: any[];
config: {
list: GridType[];
};
}>;
/** 一个字符串标签 */
label: (config: {
label: string;
}) => Promise<{
type: string;
config: {
label: string;
};
}>;
/** 输入 */
input: (globalVariable: string, config: {
label: string;
placeholder?: string | undefined;
type: 'input' | 'textarea';
color?: ViewColor | undefined;
}) => Promise<{
type: string;
bind: string;
config: {
label: string;
placeholder?: string | undefined;
type: 'input' | 'textarea';
color?: ViewColor | undefined;
};
value: any;
}>;
/** 复选框 */
checkbox: (globalVariable: string, config: {
label?: string;
type: '' | 'icon';
color?: ViewColor | undefined;
fontSet?: string | undefined;
labelPosition?: 'before' | 'after';
icon?: string;
}) => Promise<{
type: string;
bind: string;
config: {
label?: string | undefined;
type: '' | 'icon';
color?: ViewColor | undefined;
fontSet?: string | undefined;
labelPosition?: "before" | "after" | undefined;
icon?: string | undefined;
};
value: any;
}>;
/** 按钮 */
button: (config: {
label: string;
color?: ViewColor | undefined;
type: '' | 'icon' | 'flat' | 'raised' | 'stroked' | 'fab' | 'mini-fab';
fontSet?: string | undefined;
}, callback: (item: any) => Promise<any>) => Promise<{
type: string;
callback: (item: any) => Promise<any>;
config: {
label: string;
color?: ViewColor | undefined;
type: '' | 'icon' | 'flat' | 'raised' | 'stroked' | 'fab' | 'mini-fab';
fontSet?: string | undefined;
};
}>;
/** 选择框 */
select: <T_3>(globalVariable: string, config: {
label: string;
placeholder: string;
color?: ViewColor;
fontSet?: string;
multiple?: boolean;
}, list: T_3[], labelMap: (item: T_3) => string | Promise<string>, valueMap: (item: T_3) => any | Promise<any>) => Promise<{
type: string;
config: {
label: string;
placeholder: string;
color?: ViewColor | undefined;
fontSet?: string | undefined;
multiple?: boolean | undefined;
};
bind: string;
list: {
label: string;
value: any;
}[];
value: any;
}>;
/**
* 数据展示
* node-list: 根据匹配节点展示,选中会保存到 globalVariable 中
* other: 普通的数据展示
*/
showData: (globalVariable: string, config: {
type: 'node-list' | 'other';
}, data: any) => Promise<{
bind: string;
config: {
type: 'node-list' | 'other';
};
data: any;
type: string;
}>;
};
os: {
/**
* 使用 git 按需拉取仓库
* 拉取深度为1
* @param url
* @param match 使用 gitignore 风格的语法指定匹配的文件
* @param output 指定读取仓库哪个文件夹
* @param type
* @param commit
* @returns
*/
gitClone: (url: string, match?: string[] | string, output?: string, type?: 'branch' | 'tag' | 'commit', commit?: string) => Promise<Record<string, ArrayBuffer>>;
};
hint: Hint;
};
}
/** 覆盖原有的,action初始化用 */
export declare const RunnerOverrideToken: InjectionToken<typeof RuleRunner>;
export declare function safeParse(value: string): any;
export declare function safeStringify(obj: any): string;
export declare function scriptContextRunner(code: string): string;
export declare const ScriptCwdToken: InjectionToken<Path>;
export declare interface ScriptFunction<T = any> {
(util: Util, rule: RuleMap, host: ReadScopedHost, injector: Injector): Promise<T>;
}
declare function Selector<T = any>(list: TemplateStringsArray, ...args: EachFunction<T>[]): () => {
selector: string;
eachFunction: Record<string, EachFunction<T>>;
};
declare type SelectorType = string | ReturnType<typeof Selector>;
export declare type Statement<T = string> = (context: QueryContext) => T | undefined;
export declare function statementRunner(input: AutoDATA<[context: QueryContext], string>, context: QueryContext): Promise<any>;
export declare const STRING_FORMAT_LIST: readonly [readonly ["upcase", (value: string) => string], readonly ["downcase", (value: string) => string], readonly ["capitalize", (value: string) => string], readonly ["camelcase", (value: string) => string], readonly ["pascalcase", (value: string) => string], readonly ["kebabcase", (value: string) => string]];
export declare function stringSlice(str: string | Statement, start?: number, end?: number): (context: QueryContext) => string;
export declare function stringToFileBuffer(str: string): ArrayBuffer;
export declare interface TemplateOption {
contentTemplate?: 'ejs' | 'handlebars' | 'raw' | '@angular-devkit';
/** 使用不同模板引擎时可以传入该模板引擎不同参数选项调整 */
contentTemplateOptions?: any;
/**
* [@angular-devkit](https://github.com/angular/angular-cli/blob/ce45522df6af6d9c0288495695473cca70f1a2c5/packages/angular_devkit/schematics/src/rules/template.ts#L78): `__name@toUpper__` 为使用 toUpper 函数传入 name 参数,可以使用 templateContext 传入;
* 函数默认[自带](https://github.com/angular/angular-cli/blob/main/packages/angular_devkit/core/src/utils/strings.ts)
**/
pathTemplate?: 'raw' | '@angular-devkit';
pathTemplateOptions?: any;
templateContext?: Record<string, any>;
/** 移除路径的后缀 */
pathTemplateSuffix?: TemplateSuffixItem | TemplateSuffixItem[];
}
export declare class TemplateService {
#private;
/**
* 将匹配文件列表写入到指定位置
*
* 支持多种模板解析
*
* 支持部分模板引擎的变量感知
*
* @param fromList
* @param to
* @param source
* @param excludeList
* @param templateOption 模板的一些配置
* @param revoke 模板是否撤销
* @param conflictStrategy 如何和当前文件产生冲突如何处理
*/
template: (fromList: CopyFormItem[], to: string, source: FileCopyLayer['source'], excludeList?: string[], ignoreList?: string[], templateOption?: TemplateOption, revoke?: boolean, conflictStrategy?: ConflictStrategy) => Promise<void>;
}
export declare type TemplateSuffixItem = '.template' | '.template.ejs' | '.ejs' | '.handlebars' | '.hbs' | '.template.handlebars' | (string & {});
declare interface TreeOptions {
toJsonWithChildren?: boolean;
toJsonWithExtra?: boolean;
}
export declare class Util {
#private;
filePathGroup: {
currentDir: Path;
currentPath: Path;
root: Path;
scriptCwd: Path;
};
documentContext: DocumentContext;
/** [lodash](https://lodash.com/docs) */
lodash: __2.LoDashStatic;
/** 路径相关 */
path: {
join: typeof join;
normalize: typeof normalize;
resolve: typeof resolve;
relative: typeof relative;
basename: typeof basename;
dirname: typeof dirname;
isAbsolute: typeof isAbsolute;
getSystemPath: typeof getSystemPath;
split: typeof split;
};
/** 支持的解析器列表 */
parserList: LanguageOption[];
/** 独立的操作调用 */
rule: {
call: {
script: (filePath: string) => Promise<any>;
};
read: {
fileResolveByPattern: <T extends boolean = false>(filePattern?: string | undefined, selector?: string | undefined, options?: {
ignore?: string[] | undefined;
queryMode?: 0 | 1 | -1 | undefined;
all: T;
languageOption?: LanguageOption | undefined;
}) => Promise<(T extends true ? ContentResolveItem[] : ContentResolveItem) | undefined>;
fileResolve: <T_1 extends string | string[]>(filePath: T_1, languageOption?: LanguageOption | undefined) => Promise<T_1 extends string[] ? ContentResolveItem[] : ContentResolveItem>;
contentResolve: (content: string, languageOption?: LanguageOption | undefined) => Promise<ContentResolveUpdate>;
editorInput: (type: "dir" | "path" | "insertRange" | "selectRange" | "workspacePath" | "snippetParameters" | "trigger") => Promise<string | Record<string, any> | Path | {
value: string;
range: NumberTuple2;
}[] | {
value: string;
range: NumberTuple2; /** 路径相关 */
}[] | undefined>;
parseToObject: (filePath: string, type: "json" | "yaml" | "buffer" | "plain") => Promise<any>;
setting: (value: string) => Promise<any>;
};
query: {
selector: <ALL extends boolean = false>(contentResolve: ContentResolveItem, selector: string, all?: ALL, options?: QueryOptions<any> | undefined) => Promise<ALL extends true ? ContentResolveItem[] : ContentResolveItem | undefined>;
like: <Count extends number>(contentResolve: ContentResolveItem, selector: string, count: Count, options?: LikeMatchOptions | undefined) => Promise<Count extends 1 ? ContentResolveItem | undefined : ContentResolveItem[]>;
};
resolve: {
queryStatement: typeof queryStatement;
};
operator: {
replaceNode: <T_2>(list: T_2[], fileMap: (item: T_2) => ContentResolveItem | Promise<ContentResolveItem>, rangeMap: (item: T_2) => NumberTuple2 | Promise<NumberTuple2>, contentMap: (item: T_2) => string | Promise<string>) => Promise<void>;
deleteFile: (filePath: string) => Promise<void>;
newFile: (fileName: string, content: string | Buffer) => Promise<void>;
renameFile: (oldName: string, newName: string) => Promise<void>;
insertSnippet: (input: string, position: NumberTuple2 | NumberTuple2[]) => Promise<never>;
template: (fromList: CopyFormItem[], to: string, source: "local" | "git" | undefined, excludeList?: string[] | undefined, ignoreList?: string[] | undefined, templateOption?: TemplateOption | undefined, revoke?: boolean | undefined, conflictStrategy?: ConflictStrategy | undefined) => Promise<void>;
commandExec: (command: string, args: string[], cwd?: string | undefined) => Promise<void>;
};
globalVariable: {
setStringByInteractive: (input: {
name: string;
force?: boolean | undefined;
message?: string | undefined;
}[]) => Promise<{
[x: string]: any;
}>;
setBooleanByInteractive: (input: {
name: string;
force?: boolean | undefined;
message?: string | undefined;
}[]) => Promise<{
[x: string]: any;
}>;
set: (key: string, value: any) => Promise<void>;
get: (keyPath: string) => Promise<any>;
};
common: {
getData: (input: Record<string, any>, path: string | number) => Promise<any>;
didYouMean: (input: string, list: string[], options: {
threshold: number;
}) => Promise<string | null>;
rangeCompare: (input1: NumberTuple2, type: "contains" | "reverse-contains" | "intersection" | "equal" | "not-intersection", input2: NumberTuple2) => Promise<boolean>;
};
view: {
grid: (config: {
list: GridList;
}) => Promise<{
type: string;
children: any[];
config: {
list: GridType[];
};
}>;
label: (config: {
label: string;
}) => Promise<{
type: string;
config: {
label: string;
};
}>;
input: (globalVariable: string, config: {
label: string;
placeholder?: string | undefined;
type: "input" | "textarea";
color?: ViewColor | undefined;
}) => Promise<{
type: string;
bind: string;
config: {
label: string;
placeholder?: string | undefined;
type: "input" | "textarea";
color?: ViewColor | undefined;
};
value: any;
}>;
checkbox: (globalVariable: string, config: {
label?: string | undefined;
type: "" | "icon";
color?: ViewColor | undefined;
fontSet?: string | undefined;
labelPosition?: "before" | "after" | undefined;
icon?: string | undefined;
}) => Promise<{
type: string;
bind: string;
config: {
label?: string | undefined;
type: "" | "icon";
color?: ViewColor | undefined;
fontSet?: string | undefined;
labelPosition?: "before" | "after" | undefined;
icon?: string | undefined;
};
value: any;
}>;
button: (config: {
label: string;
color?: ViewColor | undefined;
type: "" | "flat" | "icon" | "raised" | "stroked" | "fab" | "mini-fab";
fontSet?: string | undefined;
}, callback: (item: any) => Promise<any>) => Promise<{
type: string;
callback: (item: any) => Promise<any>;
config: {
label: string;
color?: ViewColor | undefined;
type: "" | "flat" | "icon" | "raised" | "stroked" | "fab" | "mini-fab";
fontSet?: string | undefined;
};
}>;
select: <T_3>(globalVariable: string, config: {
label: string;
placeholder: string;
color?: ViewColor | undefined;
fontSet?: string | undefined;
multiple?: boolean | undefined;
}, list: T_3[], labelMap: (item: T_3) => string | Promise<string>, valueMap: (item: T_3) => any) => Promise<{
type: string;
config: {
label: string;
placeholder: string;
color?: ViewColor | undefined;
fontSet?: string | undefined;
multiple?: boolean | undefined;
};
bind: string;
list: {
label: string;
value: any;
}[];
value: any;
}>;
showData: (globalVariable: string, config: {
type: "node-list" | "other";
}, data: any) => Promise<{
bind: string;
config: {
type: "node-list" | "other";
};
data: any;
type: string;
}>;
};
os: {
gitClone: (url: string, match?: str