detype 2.0.7 → 3.0.0
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/LICENSE +7 -0
- package/detype.js +1 -0
- package/dist/cli.js +6 -4
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +20 -19
- package/dist/index.js +1 -1
- package/dist/{transformFile-qmpi6_2q.js → transformFile-YuwHSLHy.js} +21 -6
- package/dist/transformFile-YuwHSLHy.js.map +1 -0
- package/package.json +37 -51
- package/{README.md → readme.md} +20 -20
- package/dist/index.cjs +0 -218
- package/dist/index.d.cts +0 -44
- package/index.d.ts +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2021-present Fatih Aygün and contributors
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/detype.js
CHANGED
package/dist/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { n as transformFile, t as removeMagicCommentsFromFile } from "./transformFile-
|
|
1
|
+
import { n as transformFile, t as removeMagicCommentsFromFile } from "./transformFile-YuwHSLHy.js";
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import fastGlob from "fast-glob";
|
|
5
5
|
//#region package.json
|
|
6
|
-
var version = "
|
|
6
|
+
var version = "3.0.0";
|
|
7
7
|
//#endregion
|
|
8
8
|
//#region src/cli-lib.ts
|
|
9
9
|
const { stat, mkdir } = fs.promises;
|
|
@@ -18,7 +18,8 @@ async function cli(...args) {
|
|
|
18
18
|
console.error("Too many arguments");
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const [input] = params;
|
|
22
|
+
let output = params[1];
|
|
22
23
|
if (params.length === 0 || flags.some((flag) => flag === "-h" || flag === "--help")) {
|
|
23
24
|
printUsage();
|
|
24
25
|
return params.length > 0;
|
|
@@ -30,7 +31,6 @@ async function cli(...args) {
|
|
|
30
31
|
const removeMagic = flags.some((flag) => flag === "-m" || flag === "--remove-magic-comments");
|
|
31
32
|
const removeTsComments = flags.some((flag) => flag === "-t" || flag === "--remove-ts-comments");
|
|
32
33
|
if (removeMagic && removeTsComments) console.warn("--remove-ts-comments has no effect when --remove-magic-comments is used");
|
|
33
|
-
if (!removeMagic) [input, output] = args;
|
|
34
34
|
if (!input) {
|
|
35
35
|
console.error("No input file or directory given");
|
|
36
36
|
printUsage();
|
|
@@ -129,3 +129,5 @@ cli(...process.argv.slice(2)).then((success) => process.exit(success ? 0 : 1)).c
|
|
|
129
129
|
});
|
|
130
130
|
//#endregion
|
|
131
131
|
export {};
|
|
132
|
+
|
|
133
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","names":["pkg.version"],"sources":["../package.json","../src/cli-lib.ts","../src/cli.ts"],"sourcesContent":["","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { removeMagicCommentsFromFile, transformFile } from \"./transformFile.ts\";\nimport fastGlob from \"fast-glob\";\nimport pkg from \"../package.json\";\n\nconst { stat, mkdir } = fs.promises;\n\nexport async function cli(...args: string[]): Promise<boolean> {\n\tlet dashDash = false;\n\tconst params: string[] = [];\n\tconst flags: string[] = [];\n\tfor (const arg of args) {\n\t\tif (arg === \"--\") {\n\t\t\tdashDash = true;\n\t\t} else if (dashDash || !arg.startsWith(\"-\")) {\n\t\t\tparams.push(arg);\n\t\t} else {\n\t\t\tflags.push(arg);\n\t\t}\n\t}\n\n\tif (params.length > 2) {\n\t\tconsole.error(\"Too many arguments\");\n\t\treturn false;\n\t}\n\n\tconst [input] = params;\n\tlet output = params[1];\n\n\tif (\n\t\tparams.length === 0 ||\n\t\tflags.some((flag) => flag === \"-h\" || flag === \"--help\")\n\t) {\n\t\tprintUsage();\n\t\treturn params.length > 0;\n\t}\n\n\tif (flags.some((flag) => flag === \"-v\" || flag === \"--version\")) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.log(VERSION);\n\t\treturn true;\n\t}\n\n\tconst removeMagic = flags.some(\n\t\t(flag) => flag === \"-m\" || flag === \"--remove-magic-comments\",\n\t);\n\tconst removeTsComments = flags.some(\n\t\t(flag) => flag === \"-t\" || flag === \"--remove-ts-comments\",\n\t);\n\n\tif (removeMagic && removeTsComments) {\n\t\tconsole.warn(\n\t\t\t\"--remove-ts-comments has no effect when --remove-magic-comments is used\",\n\t\t);\n\t}\n\n\tif (!input) {\n\t\tconsole.error(\"No input file or directory given\");\n\t\tprintUsage();\n\t\treturn false;\n\t}\n\n\tconst inputStat = await stat(input);\n\n\tif (inputStat.isDirectory()) {\n\t\tif (!output) {\n\t\t\tconsole.error(\"No output directory given\");\n\t\t\tprintUsage();\n\t\t\treturn false;\n\t\t}\n\n\t\tconst files = (\n\t\t\tawait fastGlob(unixify(input + \"/**/*.{ts,tsx,vue}\"))\n\t\t).filter((file) => !file.endsWith(\".d.ts\"));\n\t\tconst dirs = [...new Set(files.map((file) => path.dirname(file)))].sort();\n\n\t\tawait mkdir(path.normalize(output), { recursive: true });\n\n\t\tfor (const dir of dirs) {\n\t\t\tconst outDir = path.join(output, path.relative(input, dir));\n\t\t\tif (outDir === output) continue;\n\t\t\tawait mkdir(path.normalize(outDir), { recursive: true });\n\t\t}\n\n\t\tfor (const file of files) {\n\t\t\tconst inputDir = path.dirname(path.relative(input, file));\n\t\t\tconst outputName = inferName(file, path.join(output, inputDir));\n\t\t\tif (removeMagic) {\n\t\t\t\tawait removeMagicCommentsFromFile(\n\t\t\t\t\tpath.normalize(file),\n\t\t\t\t\tpath.normalize(outputName),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait transformFile(path.normalize(file), path.normalize(outputName), {\n\t\t\t\t\tremoveTsComments,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\treturn true;\n\t}\n\n\tif (output) {\n\t\tconst outputStat = await stat(output).catch((error) => {\n\t\t\tif (error && error.code === \"ENOENT\") {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t});\n\n\t\tif (outputStat && outputStat.isDirectory()) {\n\t\t\toutput = inferName(input, output);\n\t\t}\n\t} else {\n\t\tif (removeMagic) {\n\t\t\tconsole.error(\n\t\t\t\t\"Output file name is required when removing magic comments\",\n\t\t\t);\n\t\t\treturn false;\n\t\t}\n\n\t\tif (input.endsWith(\".vue\")) {\n\t\t\tconsole.error(\"Output file name is required for .vue files\");\n\t\t\treturn false;\n\t\t}\n\n\t\toutput = inferName(input);\n\t}\n\n\tconst outputDir = path.dirname(output);\n\n\tif (outputDir) {\n\t\tawait mkdir(path.normalize(outputDir), { recursive: true });\n\t}\n\n\tif (removeMagic) {\n\t\tawait removeMagicCommentsFromFile(\n\t\t\tpath.normalize(input),\n\t\t\tpath.normalize(output),\n\t\t);\n\t} else {\n\t\tawait transformFile(path.normalize(input), path.normalize(output), {\n\t\t\tremoveTsComments,\n\t\t});\n\t}\n\n\treturn true;\n\n\tfunction inferName(input: string, outputDir?: string) {\n\t\tlet output: string;\n\n\t\tconst { dir, name, ext } = path.parse(input);\n\n\t\tif (removeMagic) {\n\t\t\toutput = path.join(outputDir ?? dir, `${name}${ext}`);\n\t\t} else if (ext === \".ts\") {\n\t\t\toutput = path.join(outputDir ?? dir, name + \".js\");\n\t\t} else if (ext === \".tsx\") {\n\t\t\toutput = path.join(outputDir ?? dir, name + \".jsx\");\n\t\t} else if (ext === \".vue\") {\n\t\t\toutput = path.join(outputDir ?? dir, name + \".vue\");\n\t\t} else {\n\t\t\tthrow new Error(`Unknwon file extension ${input}`);\n\t\t}\n\n\t\treturn output;\n\t}\n}\n\nfunction printUsage() {\n\tconsole.error(USAGE);\n}\n\nconst USAGE = `Usage:\n\n detype [-m | --remove-magic-comments] <INPUT> [OUTPUT]\n\n INPUT Input file or directory\n\n OUTPUT Output file or directory\n (optional if it can be inferred and it won't overwrite the source file)\n\n -t, --remove-ts-comments\n Remove @ts-ignore and @ts-expect-error comments\n\n -m, --remove-magic-comments\n Remove magic comments only, don't perform ts > js transform\n\n detype [-v | --version]\n\n Print version and exit\n\n detype [-h | --help]\n\n Print this help and exit`;\n\nconst VERSION = pkg.version;\n\n/** Unixify path */\nfunction unixify(name: string) {\n\treturn name.replaceAll(path.sep, \"/\");\n}\n","import { cli } from \"./cli-lib.ts\";\n\nconst args = process.argv.slice(2);\ncli(...args)\n\t.then((success) => process.exit(success ? 0 : 1))\n\t.catch((error) => {\n\t\tconsole.error(error);\n\t\tprocess.exit(1);\n\t});\n"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,32 +13,33 @@ interface TransformOptions$1 extends RemoveTypeOptions {
|
|
|
13
13
|
prettierOptions?: PrettierOptions | null;
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Transform TypeScript code into vanilla JavaScript without affecting the formatting
|
|
17
|
-
* @param code Source coude
|
|
18
|
-
* @param fileName File name for the source
|
|
19
|
-
* @param options Options
|
|
20
|
-
*/
|
|
16
|
+
* Transform TypeScript code into vanilla JavaScript without affecting the formatting
|
|
17
|
+
* @param code Source coude
|
|
18
|
+
* @param fileName File name for the source
|
|
19
|
+
* @param options Options
|
|
20
|
+
*/
|
|
21
21
|
declare function transform(code: string, fileName: string, options?: TransformOptions$1): Promise<string>;
|
|
22
22
|
/**
|
|
23
|
-
* Removes magic comments without performing the TS to JS transform
|
|
24
|
-
* @param code Source coude
|
|
25
|
-
* @param fileName File name for the source
|
|
26
|
-
* @param prettierOptions Options to pass to prettier
|
|
27
|
-
*/
|
|
23
|
+
* Removes magic comments without performing the TS to JS transform
|
|
24
|
+
* @param code Source coude
|
|
25
|
+
* @param fileName File name for the source
|
|
26
|
+
* @param prettierOptions Options to pass to prettier
|
|
27
|
+
*/
|
|
28
28
|
declare function removeMagicComments(code: string, fileName: string, prettierOptions?: PrettierOptions | null): Promise<string>;
|
|
29
29
|
//#endregion
|
|
30
30
|
//#region src/transformFile.d.ts
|
|
31
31
|
/**
|
|
32
|
-
* Transform the input file and write the output to another file
|
|
33
|
-
* @param inputFileName
|
|
34
|
-
* @param outputFileName
|
|
35
|
-
*/
|
|
32
|
+
* Transform the input file and write the output to another file
|
|
33
|
+
* @param inputFileName
|
|
34
|
+
* @param outputFileName
|
|
35
|
+
*/
|
|
36
36
|
declare function transformFile(inputFileName: string, outputFileName: string, options?: RemoveTypeOptions): Promise<void>;
|
|
37
37
|
/**
|
|
38
|
-
* Remove magic comments from the input file and write the output to another file
|
|
39
|
-
* @param inputFileName
|
|
40
|
-
* @param outputFileName
|
|
41
|
-
*/
|
|
38
|
+
* Remove magic comments from the input file and write the output to another file
|
|
39
|
+
* @param inputFileName
|
|
40
|
+
* @param outputFileName
|
|
41
|
+
*/
|
|
42
42
|
declare function removeMagicCommentsFromFile(inputFileName: string, outputFileName: string): Promise<void>;
|
|
43
43
|
//#endregion
|
|
44
|
-
export { type PrettierOptions, removeMagicComments, removeMagicCommentsFromFile, transform, transformFile };
|
|
44
|
+
export { type PrettierOptions, removeMagicComments, removeMagicCommentsFromFile, transform, transformFile };
|
|
45
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as transform, n as transformFile, r as removeMagicComments, t as removeMagicCommentsFromFile } from "./transformFile-
|
|
1
|
+
import { i as transform, n as transformFile, r as removeMagicComments, t as removeMagicCommentsFromFile } from "./transformFile-YuwHSLHy.js";
|
|
2
2
|
export { removeMagicComments, removeMagicCommentsFromFile, transform, transformFile };
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { transformAsync } from "@babel/core";
|
|
2
2
|
import { format, resolveConfig } from "prettier";
|
|
3
|
-
import { parse } from "@
|
|
4
|
-
import {
|
|
5
|
-
import { isComponentNode, isSimpleExpressionNode, traverse } from "@vuedx/template-ast-types";
|
|
3
|
+
import { compileScript, parse } from "@vue/compiler-sfc";
|
|
4
|
+
import { ElementTypes, NodeTypes } from "@vue/compiler-core";
|
|
6
5
|
import babelTs from "@babel/preset-typescript";
|
|
7
6
|
import fs from "node:fs";
|
|
8
7
|
//#region src/transform.ts
|
|
8
|
+
function traverseVueAst(root, visitor) {
|
|
9
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
10
|
+
function walk(node) {
|
|
11
|
+
if (!node || typeof node !== "object" || typeof node.type !== "number") return;
|
|
12
|
+
if (seen.has(node)) return;
|
|
13
|
+
seen.add(node);
|
|
14
|
+
visitor.enter(node);
|
|
15
|
+
for (const value of Object.values(node)) if (Array.isArray(value)) for (const item of value) walk(item);
|
|
16
|
+
else if (value && typeof value === "object") walk(value);
|
|
17
|
+
}
|
|
18
|
+
walk(root);
|
|
19
|
+
}
|
|
9
20
|
function getDefinePropsObject(content) {
|
|
10
21
|
const matched = /\sprops:\s*\{/m.exec(content);
|
|
11
22
|
if (matched) {
|
|
@@ -93,9 +104,10 @@ async function removeTypesFromVueSfcScript(code, fileName, script, templateAst,
|
|
|
93
104
|
if (script === null || script.lang !== "ts") return code;
|
|
94
105
|
if (script.setup && templateAst) {
|
|
95
106
|
const expressions = /* @__PURE__ */ new Set();
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
107
|
+
traverseVueAst(templateAst, { enter(node) {
|
|
108
|
+
const n = node;
|
|
109
|
+
if (n.type === NodeTypes.SIMPLE_EXPRESSION && !n.isStatic) expressions.add(`[${n.content}]`);
|
|
110
|
+
else if (n.type === NodeTypes.ELEMENT && n.tagType === ElementTypes.COMPONENT) expressions.add(`[${n.tag}]`);
|
|
99
111
|
} });
|
|
100
112
|
script.content += "/* @detype: remove-after-this */" + [...expressions].join(";");
|
|
101
113
|
}
|
|
@@ -142,6 +154,7 @@ async function removeMagicComments(code, fileName, prettierOptions) {
|
|
|
142
154
|
const REPLACE_COMMENT = "// @detype: replace\n";
|
|
143
155
|
const WITH_COMMENT = "// @detype: with\n";
|
|
144
156
|
const END_COMMENT = "// @detype: end\n";
|
|
157
|
+
code = code.replaceAll("\r\n", "\n");
|
|
145
158
|
let start = code.indexOf(REPLACE_COMMENT);
|
|
146
159
|
let startEnd = start + 20;
|
|
147
160
|
while (start >= 0) {
|
|
@@ -188,3 +201,5 @@ async function removeMagicCommentsFromFile(inputFileName, outputFileName) {
|
|
|
188
201
|
}
|
|
189
202
|
//#endregion
|
|
190
203
|
export { transform as i, transformFile as n, removeMagicComments as r, removeMagicCommentsFromFile as t };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=transformFile-YuwHSLHy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformFile-YuwHSLHy.js","names":["parseVueSfc","VueNodeTypes","VueElementTypes"],"sources":["../src/transform.ts","../src/transformFile.ts"],"sourcesContent":["import {\n\ttransformAsync,\n\ttype TransformOptions as BabelTransformOptions,\n} from \"@babel/core\";\nimport type { VisitNodeObject, Node } from \"@babel/traverse\";\nimport { format } from \"prettier\";\nimport {\n\tcompileScript,\n\tparse as parseVueSfc,\n\ttype SFCTemplateBlock as VueSfcTemplateBlock,\n\ttype SFCScriptBlock as VueSfcScriptBlock,\n} from \"@vue/compiler-sfc\";\nimport {\n\tElementTypes as VueElementTypes,\n\tNodeTypes as VueNodeTypes,\n\ttype RootNode as VueRootNode,\n} from \"@vue/compiler-core\";\nimport type { PrettierOptions } from \".\";\n\nfunction traverseVueAst(\n\troot: VueRootNode,\n\tvisitor: { enter(node: unknown): void },\n): void {\n\tconst seen = new WeakSet<object>();\n\tfunction walk(node: unknown): void {\n\t\tif (\n\t\t\t!node ||\n\t\t\ttypeof node !== \"object\" ||\n\t\t\ttypeof (node as { type?: unknown }).type !== \"number\"\n\t\t) {\n\t\t\treturn;\n\t\t}\n\t\tif (seen.has(node)) return;\n\t\tseen.add(node);\n\t\tvisitor.enter(node);\n\t\tfor (const value of Object.values(node)) {\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\tfor (const item of value) walk(item);\n\t\t\t} else if (value && typeof value === \"object\") {\n\t\t\t\twalk(value);\n\t\t\t}\n\t\t}\n\t}\n\twalk(root);\n}\n\n// @ts-expect-error: No typinggs needed\nimport babelTs from \"@babel/preset-typescript\";\n\nfunction getDefinePropsObject(content: string) {\n\tconst matched = /\\sprops:\\s*\\{/m.exec(content);\n\tif (matched) {\n\t\tconst startContentIndex = matched.index + matched[0].length - 1;\n\t\tlet leftBracketCount = 1;\n\t\tlet endContentIndex = startContentIndex + 1;\n\t\twhile (leftBracketCount) {\n\t\t\tif (content.charAt(endContentIndex) === \"{\") {\n\t\t\t\tleftBracketCount++;\n\t\t\t} else if (content.charAt(endContentIndex) === \"}\") {\n\t\t\t\tleftBracketCount--;\n\t\t\t}\n\t\t\tendContentIndex++;\n\t\t}\n\t\treturn content.substring(startContentIndex, endContentIndex);\n\t}\n\treturn \"\";\n}\n\ntype VueElementNode = VueSfcTemplateBlock[\"ast\"];\n\nexport interface RemoveTypeOptions {\n\t/** Whether to remove ts-ignore and ts-expect-error comments */\n\tremoveTsComments?: boolean;\n\t/** Escape hatch for customizing Babel configuration */\n\tcustomizeBabelConfig?(config: BabelTransformOptions): void;\n}\n\nexport interface TransformOptions extends RemoveTypeOptions {\n\t/** Prettier options */\n\tprettierOptions?: PrettierOptions | null;\n}\n\n/**\n * Transform TypeScript code into vanilla JavaScript without affecting the formatting\n * @param code Source coude\n * @param fileName File name for the source\n * @param options Options\n */\nexport async function transform(\n\tcode: string,\n\tfileName: string,\n\toptions: TransformOptions = {},\n): Promise<string> {\n\tconst { prettierOptions, ...removeTypeOptions } = options;\n\n\tconst originalCode = code;\n\tconst originalFileName = fileName;\n\tlet propsContent = \"\";\n\tlet emitsContent = \"\";\n\n\tcode = code.replaceAll(\"\\r\\n\", \"\\n\");\n\n\tif (fileName.endsWith(\".vue\")) {\n\t\tconst parsedVue = parseVueSfc(code);\n\n\t\tif (\n\t\t\tparsedVue.descriptor.script?.lang !== \"ts\" &&\n\t\t\tparsedVue.descriptor.scriptSetup?.lang !== \"ts\"\n\t\t) {\n\t\t\t// No TypeScript, don't touch it\n\t\t\treturn originalCode;\n\t\t}\n\n\t\tlet { script: script1, scriptSetup: script2 } = parsedVue.descriptor;\n\n\t\tconst isContainsDefinePropsType =\n\t\t\tscript2?.content.match(/defineProps\\s*</m);\n\t\tconst isContainsDefineEmitType = script2?.content.match(/defineEmits\\s*</m);\n\n\t\tif (isContainsDefinePropsType || isContainsDefineEmitType) {\n\t\t\tconst { content } = compileScript(parsedVue.descriptor as any, {\n\t\t\t\tid: \"xxxxxxx\",\n\t\t\t});\n\n\t\t\tif (isContainsDefinePropsType) {\n\t\t\t\tpropsContent = getDefinePropsObject(content);\n\t\t\t}\n\t\t\tif (isContainsDefineEmitType) {\n\t\t\t\temitsContent = content.match(/\\semits:\\s(\\[.*\\]?)/m)?.[1] || \"\";\n\t\t\t}\n\t\t}\n\n\t\t// Process the second script first to simplify code location handling\n\t\tif (\n\t\t\tscript1 &&\n\t\t\tscript2 &&\n\t\t\tscript1.loc.start.offset < script2.loc.start.offset\n\t\t) {\n\t\t\t[script2, script1] = [script1, script2];\n\t\t}\n\n\t\tcode = await removeTypesFromVueSfcScript(\n\t\t\tcode,\n\t\t\tfileName,\n\t\t\tscript1,\n\t\t\tparsedVue.descriptor.template?.ast,\n\t\t\tremoveTypeOptions,\n\t\t);\n\n\t\tcode = await removeTypesFromVueSfcScript(\n\t\t\tcode,\n\t\t\tfileName,\n\t\t\tscript2,\n\t\t\tparsedVue.descriptor.template?.ast,\n\t\t\tremoveTypeOptions,\n\t\t);\n\t} else {\n\t\tcode = await removeTypes(code, fileName, removeTypeOptions);\n\t}\n\n\tif (propsContent) {\n\t\tcode = code.replace(\"defineProps(\", (str) => `${str}${propsContent}`);\n\t}\n\tif (emitsContent) {\n\t\tcode = code.replace(\"defineEmits(\", (str) => `${str}${emitsContent}`);\n\t}\n\n\tcode = await format(code, {\n\t\t...prettierOptions,\n\t\tfilepath: originalFileName,\n\t});\n\n\treturn code;\n}\n\nasync function removeTypes(\n\tcode: string,\n\tfileName: string,\n\toptions: RemoveTypeOptions,\n) {\n\t// We want to collapse newline runs created by removing types while preserving\n\t// newline runes in the original code. This is especially important for\n\t// template literals, which can contain literal newlines.\n\t// Keep track of how many newlines in a newline run were replaced.\n\tcode = code.replace(\n\t\t/\\n\\n+/g,\n\t\t(match) => `\\n/* @detype: empty-line=${match.length} */\\n`,\n\t);\n\tcode = processMagicComments(code);\n\n\t// Babel visitor to remove leading comments\n\tconst removeComments: VisitNodeObject<unknown, Node> = {\n\t\tenter(p) {\n\t\t\tif (!p.node.leadingComments) return;\n\n\t\t\tfor (let i = p.node.leadingComments.length - 1; i >= 0; i--) {\n\t\t\t\tconst comment = p.node.leadingComments[i]!;\n\n\t\t\t\tif (\n\t\t\t\t\tcode.slice(comment.end).match(/^\\s*\\n\\s*\\n/) ||\n\t\t\t\t\tcomment.value.includes(\"@detype: empty-line\")\n\t\t\t\t) {\n\t\t\t\t\t// There is at least one empty line between the comment and the TypeScript specific construct\n\t\t\t\t\t// We should keep this comment and those before it\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcomment.value = \"@detype: remove-me\";\n\t\t\t}\n\t\t},\n\t};\n\n\tconst babelConfig: BabelTransformOptions = {\n\t\tfilename: fileName,\n\t\tretainLines: true,\n\t\tplugins: [\n\t\t\t// Plugin to remove leading comments attached to TypeScript-only constructs\n\t\t\t{\n\t\t\t\tname: \"detype-comment-remover\",\n\t\t\t\tvisitor: {\n\t\t\t\t\tTSTypeAliasDeclaration: removeComments,\n\t\t\t\t\tTSInterfaceDeclaration: removeComments,\n\t\t\t\t\tTSDeclareFunction: removeComments,\n\t\t\t\t\tTSDeclareMethod: removeComments,\n\t\t\t\t\tTSImportType: removeComments,\n\t\t\t\t},\n\t\t\t},\n\t\t].filter(Boolean),\n\t\tpresets: [babelTs],\n\t\tgeneratorOpts: {\n\t\t\tshouldPrintComment: (comment) =>\n\t\t\t\tcomment !== \"@detype: remove-me\" &&\n\t\t\t\t(!options.removeTsComments ||\n\t\t\t\t\t!comment.match(/^\\s*(@ts-ignore|@ts-expect-error)/)),\n\t\t},\n\t};\n\n\tif (options.customizeBabelConfig) {\n\t\toptions.customizeBabelConfig(babelConfig);\n\t}\n\n\tconst babelOutput = await transformAsync(code, babelConfig);\n\n\tif (\n\t\t!babelOutput ||\n\t\tbabelOutput.code === undefined ||\n\t\tbabelOutput.code === null\n\t) {\n\t\tthrow new Error(\"Babel error\");\n\t}\n\n\treturn (\n\t\tbabelOutput.code\n\t\t\t.replaceAll(/\\n\\n*/g, \"\\n\")\n\t\t\t// Subtract 2 from the newline count because we inserted two surrounding\n\t\t\t// newlines when we initially created the detype: empty-line comment.\n\t\t\t.replace(/\\/\\* @detype: empty-line=([0-9]+) \\*\\//g, (_match, p1) =>\n\t\t\t\t`\\n`.repeat(p1 - 2),\n\t\t\t)\n\t);\n}\n\nasync function removeTypesFromVueSfcScript(\n\tcode: string,\n\tfileName: string,\n\tscript: VueSfcScriptBlock | null,\n\ttemplateAst: VueElementNode | undefined,\n\toptions: RemoveTypeOptions,\n) {\n\tif (script === null || script.lang !== \"ts\") return code;\n\n\tif (script.setup && templateAst) {\n\t\t// Babel TypeScript preset removes unused exports thinking they may be type-only exports.\n\t\t// We have to mark every import that the template references to mark them as used.\n\n\t\tconst expressions = new Set<string>();\n\n\t\ttraverseVueAst(templateAst, {\n\t\t\tenter(node) {\n\t\t\t\tconst n = node as {\n\t\t\t\t\ttype: number;\n\t\t\t\t\tisStatic?: boolean;\n\t\t\t\t\tcontent?: string;\n\t\t\t\t\ttagType?: number;\n\t\t\t\t\ttag?: string;\n\t\t\t\t};\n\t\t\t\tif (n.type === VueNodeTypes.SIMPLE_EXPRESSION && !n.isStatic) {\n\t\t\t\t\texpressions.add(`[${n.content}]`);\n\t\t\t\t} else if (\n\t\t\t\t\tn.type === VueNodeTypes.ELEMENT &&\n\t\t\t\t\tn.tagType === VueElementTypes.COMPONENT\n\t\t\t\t) {\n\t\t\t\t\texpressions.add(`[${n.tag}]`);\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\n\t\t// We'll simply add them at the end of the template\n\t\tscript.content +=\n\t\t\t\"/* @detype: remove-after-this */\" + [...expressions].join(\";\");\n\t}\n\n\tlet scriptCode = await removeTypes(script.content, fileName + \".ts\", options);\n\n\tconst removeAfterIndex = scriptCode.indexOf(\n\t\t\"/* @detype: remove-after-this */\",\n\t);\n\n\tif (removeAfterIndex >= 0) {\n\t\tscriptCode = scriptCode.slice(0, removeAfterIndex);\n\t}\n\n\tlet before = code.slice(0, script.loc.start.offset);\n\tconst after = code.slice(script.loc.end.offset);\n\n\t// We have to backtrack to remove lang=\"ts\", not fool-proof but should work for all reasonable code\n\tconst matches = before.match(/\\blang\\s*=\\s*[\"']ts[\"']/);\n\n\tif (matches) {\n\t\tconst lastMatch = matches[matches.length - 1]!;\n\t\tconst lastMatchIndex = before.lastIndexOf(lastMatch);\n\t\tbefore =\n\t\t\tbefore.slice(0, lastMatchIndex) +\n\t\t\tbefore.slice(lastMatchIndex + lastMatch.length);\n\t}\n\n\treturn before + scriptCode + after;\n}\n\nexport function processMagicComments(input: string): string {\n\tconst REPLACE_COMMENT = \"// @detype: replace\\n\";\n\tconst WITH_COMMENT = \"// @detype: with\\n\";\n\tconst END_COMMENT = \"// @detype: end\\n\";\n\n\tlet start = input.indexOf(REPLACE_COMMENT);\n\n\twhile (start >= 0) {\n\t\tconst middle = input.indexOf(WITH_COMMENT, start);\n\t\tif (middle < 0) return input;\n\t\tconst middleEnd = middle + WITH_COMMENT.length;\n\n\t\tconst end = input.indexOf(END_COMMENT, middleEnd);\n\t\tif (end < 0) return input;\n\t\tconst endEnd = end + END_COMMENT.length;\n\n\t\tconst before = input.slice(0, start);\n\t\tconst newText = input.slice(middleEnd, end).replaceAll(/^\\s*\\/\\//gm, \"\");\n\t\tconst after = input.slice(endEnd);\n\n\t\tinput = before + newText + after;\n\n\t\tstart = input.indexOf(REPLACE_COMMENT, before.length + newText.length);\n\t}\n\n\treturn input;\n}\n\n/**\n * Removes magic comments without performing the TS to JS transform\n * @param code Source coude\n * @param fileName File name for the source\n * @param prettierOptions Options to pass to prettier\n */\nexport async function removeMagicComments(\n\tcode: string,\n\tfileName: string,\n\tprettierOptions?: PrettierOptions | null,\n): Promise<string> {\n\tconst REPLACE_COMMENT = \"// @detype: replace\\n\";\n\tconst WITH_COMMENT = \"// @detype: with\\n\";\n\tconst END_COMMENT = \"// @detype: end\\n\";\n\n\tcode = code.replaceAll(\"\\r\\n\", \"\\n\");\n\n\tlet start = code.indexOf(REPLACE_COMMENT);\n\tlet startEnd = start + REPLACE_COMMENT.length;\n\n\twhile (start >= 0) {\n\t\tconst middle = code.indexOf(WITH_COMMENT, start);\n\t\tif (middle < 0) return code;\n\t\tconst middleEnd = middle + WITH_COMMENT.length;\n\n\t\tconst end = code.indexOf(END_COMMENT, middleEnd);\n\t\tif (end < 0) return code;\n\t\tconst endEnd = end + END_COMMENT.length;\n\n\t\tconst before = code.slice(0, start);\n\t\tconst keptText = code.slice(startEnd, middle);\n\t\tconst after = code.slice(endEnd);\n\n\t\tcode = before + keptText + after;\n\n\t\tstart = code.indexOf(REPLACE_COMMENT, before.length + keptText.length);\n\t\tstartEnd = start + REPLACE_COMMENT.length;\n\t}\n\n\tcode = await format(code, {\n\t\t...prettierOptions,\n\t\tfilepath: fileName,\n\t});\n\n\treturn code;\n}\n","import fs from \"node:fs\";\nimport {\n\ttransform,\n\tremoveMagicComments,\n\ttype RemoveTypeOptions,\n} from \"./transform.ts\";\nimport { resolveConfig } from \"prettier\";\n\nconst { readFile, writeFile } = fs.promises;\n\n/**\n * Transform the input file and write the output to another file\n * @param inputFileName\n * @param outputFileName\n */\nexport async function transformFile(\n\tinputFileName: string,\n\toutputFileName: string,\n\toptions: RemoveTypeOptions = {},\n): Promise<void> {\n\tconst code = await readFile(inputFileName, \"utf-8\");\n\tconst prettierOptions = await resolveConfig(inputFileName);\n\tconst output = await transform(code, inputFileName, {\n\t\tprettierOptions,\n\t\t...options,\n\t});\n\tawait writeFile(outputFileName, output, \"utf-8\");\n}\n\n/**\n * Remove magic comments from the input file and write the output to another file\n * @param inputFileName\n * @param outputFileName\n */\nexport async function removeMagicCommentsFromFile(\n\tinputFileName: string,\n\toutputFileName: string,\n): Promise<void> {\n\tconst code = await readFile(inputFileName, \"utf-8\");\n\tconst prettierConfig = await resolveConfig(inputFileName);\n\tconst output = await removeMagicComments(code, inputFileName, prettierConfig);\n\tawait writeFile(outputFileName, output, \"utf-8\");\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,75 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "detype",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Removes TypeScript type annotations but keeps the formatting",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
5
|
+
"keywords": [
|
|
6
|
+
"typescript",
|
|
7
|
+
"formatting",
|
|
8
|
+
"vue",
|
|
9
|
+
"sfc"
|
|
10
|
+
],
|
|
11
|
+
"author": "Fatih Aygün <cyco130@gmail.com>",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"repository": "github:cyco130/detype",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/cyco130/detype/issues"
|
|
17
16
|
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
17
|
+
"homepage": "https://github.com/cyco130/detype#readme",
|
|
18
|
+
"bin": {
|
|
19
|
+
"detype": "./detype.js"
|
|
21
20
|
},
|
|
22
21
|
"files": [
|
|
23
|
-
"dist
|
|
24
|
-
"
|
|
22
|
+
"dist",
|
|
23
|
+
"detype.js"
|
|
25
24
|
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./dist/index.js"
|
|
28
|
+
},
|
|
26
29
|
"dependencies": {
|
|
27
30
|
"@babel/core": "^7.29.0",
|
|
28
31
|
"@babel/preset-typescript": "^7.28.5",
|
|
29
32
|
"@babel/traverse": "^7.29.0",
|
|
30
|
-
"@vue/compiler-
|
|
31
|
-
"@vue/compiler-sfc": "^3.5.
|
|
32
|
-
"@vuedx/compiler-sfc": "0.7.1",
|
|
33
|
-
"@vuedx/template-ast-types": "0.7.1",
|
|
33
|
+
"@vue/compiler-core": "^3.5.34",
|
|
34
|
+
"@vue/compiler-sfc": "^3.5.34",
|
|
34
35
|
"fast-glob": "^3.3.3",
|
|
35
|
-
"prettier": "^3.8.
|
|
36
|
+
"prettier": "^3.8.3"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
|
-
"@cyco130/eslint-config": "^
|
|
39
|
+
"@cyco130/eslint-config": "^9.0.0",
|
|
39
40
|
"@types/babel__core": "^7.20.5",
|
|
40
41
|
"@types/babel__traverse": "^7.28.0",
|
|
41
|
-
"@types/node": "
|
|
42
|
-
"eslint": "^10.
|
|
43
|
-
"
|
|
44
|
-
"tsdown": "^0.
|
|
45
|
-
"typescript": "^6.0.
|
|
46
|
-
"vitest": "4.1.
|
|
42
|
+
"@types/node": "^22.19.19",
|
|
43
|
+
"eslint": "^10.3.0",
|
|
44
|
+
"publint": "^0.3.20",
|
|
45
|
+
"tsdown": "^0.22.0",
|
|
46
|
+
"typescript": "^6.0.3",
|
|
47
|
+
"vitest": "^4.1.6"
|
|
47
48
|
},
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"url": "git+https://github.com/cyco130/detype.git"
|
|
51
|
-
},
|
|
52
|
-
"keywords": [
|
|
53
|
-
"typescript",
|
|
54
|
-
"formatting",
|
|
55
|
-
"vue",
|
|
56
|
-
"sfc"
|
|
57
|
-
],
|
|
58
|
-
"author": "Fatih Aygün <cyco130@gmail.com>",
|
|
59
|
-
"license": "MIT",
|
|
60
|
-
"bugs": {
|
|
61
|
-
"url": "https://github.com/cyco130/detype/issues"
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": "22 || 24 || 25 || 26"
|
|
62
51
|
},
|
|
63
|
-
"homepage": "https://github.com/cyco130/detype#readme",
|
|
64
52
|
"scripts": {
|
|
65
|
-
"build": "tsdown",
|
|
53
|
+
"build": "tsdown --clean",
|
|
66
54
|
"dev": "tsdown --watch",
|
|
67
55
|
"test": "pnpm run /^test:/",
|
|
68
|
-
"test:
|
|
56
|
+
"test:typecheck": "tsc -p tsconfig.json --noEmit",
|
|
57
|
+
"test:lint": "eslint . --max-warnings 0",
|
|
69
58
|
"test:unit": "vitest run",
|
|
70
|
-
"
|
|
71
|
-
"cq:lint": "eslint src --max-warnings 0",
|
|
72
|
-
"cq:prettier": "prettier --check test-files --ignore-unknown . '!pnpm-lock.yaml'",
|
|
73
|
-
"format": "prettier . --write --ignore-path .gitignore --ignore-unknown . '!pnpm-lock.yaml'"
|
|
59
|
+
"test:package": "publint"
|
|
74
60
|
}
|
|
75
61
|
}
|
package/{README.md → readme.md}
RENAMED
|
@@ -22,13 +22,13 @@ let x: string;
|
|
|
22
22
|
// This comment should be deleted
|
|
23
23
|
// Ditto for this
|
|
24
24
|
interface Foo {
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
// This should go too
|
|
26
|
+
bar: number;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// This comment should also be kept
|
|
30
30
|
export function bar(foo: Foo): Date {
|
|
31
|
-
|
|
31
|
+
return new Date();
|
|
32
32
|
}
|
|
33
33
|
```
|
|
34
34
|
|
|
@@ -41,7 +41,7 @@ let x;
|
|
|
41
41
|
|
|
42
42
|
// This comment should also be kept
|
|
43
43
|
export function bar(foo) {
|
|
44
|
-
|
|
44
|
+
return new Date();
|
|
45
45
|
}
|
|
46
46
|
```
|
|
47
47
|
|
|
@@ -113,34 +113,34 @@ console.log("Hello from TypeScript");
|
|
|
113
113
|
```ts
|
|
114
114
|
// Transform TypeScript code into vanilla JavaScript without affecting the formatting
|
|
115
115
|
function transform(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
// Source code
|
|
117
|
+
code: string,
|
|
118
|
+
// File name for the source
|
|
119
|
+
fileName: string,
|
|
120
|
+
// Options to pass to prettier
|
|
121
|
+
prettierOptions?: PrettierOptions | null,
|
|
122
122
|
): Promise<string>;
|
|
123
123
|
|
|
124
124
|
// Transform the input file and write the output to another file
|
|
125
125
|
function transformFile(
|
|
126
|
-
|
|
127
|
-
|
|
126
|
+
inputFileName: string,
|
|
127
|
+
outputFileName: string,
|
|
128
128
|
): Promise<void>;
|
|
129
129
|
|
|
130
130
|
// Remove magic comments without performing the TS to JS transform
|
|
131
131
|
export async function removeMagicComments(
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
132
|
+
// Source code
|
|
133
|
+
code: string,
|
|
134
|
+
// File name for the source
|
|
135
|
+
fileName: string,
|
|
136
|
+
// Options to pass to prettier
|
|
137
|
+
prettierOptions?: PrettierOptions | null,
|
|
138
138
|
): Promise<string>;
|
|
139
139
|
|
|
140
140
|
// Remove magic comments from the input file and write the output to another file
|
|
141
141
|
export async function removeMagicCommentsFromFile(
|
|
142
|
-
|
|
143
|
-
|
|
142
|
+
inputFileName: string,
|
|
143
|
+
outputFileName: string,
|
|
144
144
|
): Promise<void>;
|
|
145
145
|
```
|
|
146
146
|
|
package/dist/index.cjs
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
//#region \0rolldown/runtime.js
|
|
3
|
-
var __create = Object.create;
|
|
4
|
-
var __defProp = Object.defineProperty;
|
|
5
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
-
var __copyProps = (to, from, except, desc) => {
|
|
10
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
13
|
-
get: ((k) => from[k]).bind(null, key),
|
|
14
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
20
|
-
value: mod,
|
|
21
|
-
enumerable: true
|
|
22
|
-
}) : target, mod));
|
|
23
|
-
//#endregion
|
|
24
|
-
let _babel_core = require("@babel/core");
|
|
25
|
-
let prettier = require("prettier");
|
|
26
|
-
let _vuedx_compiler_sfc = require("@vuedx/compiler-sfc");
|
|
27
|
-
let _vue_compiler_sfc = require("@vue/compiler-sfc");
|
|
28
|
-
let _vuedx_template_ast_types = require("@vuedx/template-ast-types");
|
|
29
|
-
let _babel_preset_typescript = require("@babel/preset-typescript");
|
|
30
|
-
_babel_preset_typescript = __toESM(_babel_preset_typescript);
|
|
31
|
-
let node_fs = require("node:fs");
|
|
32
|
-
node_fs = __toESM(node_fs);
|
|
33
|
-
//#region src/transform.ts
|
|
34
|
-
function getDefinePropsObject(content) {
|
|
35
|
-
const matched = /\sprops:\s*\{/m.exec(content);
|
|
36
|
-
if (matched) {
|
|
37
|
-
const startContentIndex = matched.index + matched[0].length - 1;
|
|
38
|
-
let leftBracketCount = 1;
|
|
39
|
-
let endContentIndex = startContentIndex + 1;
|
|
40
|
-
while (leftBracketCount) {
|
|
41
|
-
if (content.charAt(endContentIndex) === "{") leftBracketCount++;
|
|
42
|
-
else if (content.charAt(endContentIndex) === "}") leftBracketCount--;
|
|
43
|
-
endContentIndex++;
|
|
44
|
-
}
|
|
45
|
-
return content.substring(startContentIndex, endContentIndex);
|
|
46
|
-
}
|
|
47
|
-
return "";
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Transform TypeScript code into vanilla JavaScript without affecting the formatting
|
|
51
|
-
* @param code Source coude
|
|
52
|
-
* @param fileName File name for the source
|
|
53
|
-
* @param options Options
|
|
54
|
-
*/
|
|
55
|
-
async function transform(code, fileName, options = {}) {
|
|
56
|
-
const { prettierOptions, ...removeTypeOptions } = options;
|
|
57
|
-
const originalCode = code;
|
|
58
|
-
const originalFileName = fileName;
|
|
59
|
-
let propsContent = "";
|
|
60
|
-
let emitsContent = "";
|
|
61
|
-
code = code.replaceAll("\r\n", "\n");
|
|
62
|
-
if (fileName.endsWith(".vue")) {
|
|
63
|
-
const parsedVue = (0, _vuedx_compiler_sfc.parse)(code);
|
|
64
|
-
if (parsedVue.descriptor.script?.lang !== "ts" && parsedVue.descriptor.scriptSetup?.lang !== "ts") return originalCode;
|
|
65
|
-
let { script: script1, scriptSetup: script2 } = parsedVue.descriptor;
|
|
66
|
-
const isContainsDefinePropsType = script2?.content.match(/defineProps\s*</m);
|
|
67
|
-
const isContainsDefineEmitType = script2?.content.match(/defineEmits\s*</m);
|
|
68
|
-
if (isContainsDefinePropsType || isContainsDefineEmitType) {
|
|
69
|
-
const { content } = (0, _vue_compiler_sfc.compileScript)(parsedVue.descriptor, { id: "xxxxxxx" });
|
|
70
|
-
if (isContainsDefinePropsType) propsContent = getDefinePropsObject(content);
|
|
71
|
-
if (isContainsDefineEmitType) emitsContent = content.match(/\semits:\s(\[.*\]?)/m)?.[1] || "";
|
|
72
|
-
}
|
|
73
|
-
if (script1 && script2 && script1.loc.start.offset < script2.loc.start.offset) [script2, script1] = [script1, script2];
|
|
74
|
-
code = await removeTypesFromVueSfcScript(code, fileName, script1, parsedVue.descriptor.template?.ast, removeTypeOptions);
|
|
75
|
-
code = await removeTypesFromVueSfcScript(code, fileName, script2, parsedVue.descriptor.template?.ast, removeTypeOptions);
|
|
76
|
-
} else code = await removeTypes(code, fileName, removeTypeOptions);
|
|
77
|
-
if (propsContent) code = code.replace("defineProps(", (str) => `${str}${propsContent}`);
|
|
78
|
-
if (emitsContent) code = code.replace("defineEmits(", (str) => `${str}${emitsContent}`);
|
|
79
|
-
code = await (0, prettier.format)(code, {
|
|
80
|
-
...prettierOptions,
|
|
81
|
-
filepath: originalFileName
|
|
82
|
-
});
|
|
83
|
-
return code;
|
|
84
|
-
}
|
|
85
|
-
async function removeTypes(code, fileName, options) {
|
|
86
|
-
code = code.replace(/\n\n+/g, (match) => `\n/* @detype: empty-line=${match.length} */\n`);
|
|
87
|
-
code = processMagicComments(code);
|
|
88
|
-
const removeComments = { enter(p) {
|
|
89
|
-
if (!p.node.leadingComments) return;
|
|
90
|
-
for (let i = p.node.leadingComments.length - 1; i >= 0; i--) {
|
|
91
|
-
const comment = p.node.leadingComments[i];
|
|
92
|
-
if (code.slice(comment.end).match(/^\s*\n\s*\n/) || comment.value.includes("@detype: empty-line")) break;
|
|
93
|
-
comment.value = "@detype: remove-me";
|
|
94
|
-
}
|
|
95
|
-
} };
|
|
96
|
-
const babelConfig = {
|
|
97
|
-
filename: fileName,
|
|
98
|
-
retainLines: true,
|
|
99
|
-
plugins: [{
|
|
100
|
-
name: "detype-comment-remover",
|
|
101
|
-
visitor: {
|
|
102
|
-
TSTypeAliasDeclaration: removeComments,
|
|
103
|
-
TSInterfaceDeclaration: removeComments,
|
|
104
|
-
TSDeclareFunction: removeComments,
|
|
105
|
-
TSDeclareMethod: removeComments,
|
|
106
|
-
TSImportType: removeComments
|
|
107
|
-
}
|
|
108
|
-
}].filter(Boolean),
|
|
109
|
-
presets: [_babel_preset_typescript.default],
|
|
110
|
-
generatorOpts: { shouldPrintComment: (comment) => comment !== "@detype: remove-me" && (!options.removeTsComments || !comment.match(/^\s*(@ts-ignore|@ts-expect-error)/)) }
|
|
111
|
-
};
|
|
112
|
-
if (options.customizeBabelConfig) options.customizeBabelConfig(babelConfig);
|
|
113
|
-
const babelOutput = await (0, _babel_core.transformAsync)(code, babelConfig);
|
|
114
|
-
if (!babelOutput || babelOutput.code === void 0 || babelOutput.code === null) throw new Error("Babel error");
|
|
115
|
-
return babelOutput.code.replaceAll(/\n\n*/g, "\n").replace(/\/\* @detype: empty-line=([0-9]+) \*\//g, (_match, p1) => `\n`.repeat(p1 - 2));
|
|
116
|
-
}
|
|
117
|
-
async function removeTypesFromVueSfcScript(code, fileName, script, templateAst, options) {
|
|
118
|
-
if (script === null || script.lang !== "ts") return code;
|
|
119
|
-
if (script.setup && templateAst) {
|
|
120
|
-
const expressions = /* @__PURE__ */ new Set();
|
|
121
|
-
(0, _vuedx_template_ast_types.traverse)(templateAst, { enter(node) {
|
|
122
|
-
if ((0, _vuedx_template_ast_types.isSimpleExpressionNode)(node) && !node.isStatic) expressions.add(`[${node.content}]`);
|
|
123
|
-
else if ((0, _vuedx_template_ast_types.isComponentNode)(node)) expressions.add(`[${node.tag}]`);
|
|
124
|
-
} });
|
|
125
|
-
script.content += "/* @detype: remove-after-this */" + [...expressions].join(";");
|
|
126
|
-
}
|
|
127
|
-
let scriptCode = await removeTypes(script.content, fileName + ".ts", options);
|
|
128
|
-
const removeAfterIndex = scriptCode.indexOf("/* @detype: remove-after-this */");
|
|
129
|
-
if (removeAfterIndex >= 0) scriptCode = scriptCode.slice(0, removeAfterIndex);
|
|
130
|
-
let before = code.slice(0, script.loc.start.offset);
|
|
131
|
-
const after = code.slice(script.loc.end.offset);
|
|
132
|
-
const matches = before.match(/\blang\s*=\s*["']ts["']/);
|
|
133
|
-
if (matches) {
|
|
134
|
-
const lastMatch = matches[matches.length - 1];
|
|
135
|
-
const lastMatchIndex = before.lastIndexOf(lastMatch);
|
|
136
|
-
before = before.slice(0, lastMatchIndex) + before.slice(lastMatchIndex + lastMatch.length);
|
|
137
|
-
}
|
|
138
|
-
return before + scriptCode + after;
|
|
139
|
-
}
|
|
140
|
-
function processMagicComments(input) {
|
|
141
|
-
const REPLACE_COMMENT = "// @detype: replace\n";
|
|
142
|
-
const WITH_COMMENT = "// @detype: with\n";
|
|
143
|
-
const END_COMMENT = "// @detype: end\n";
|
|
144
|
-
let start = input.indexOf(REPLACE_COMMENT);
|
|
145
|
-
while (start >= 0) {
|
|
146
|
-
const middle = input.indexOf(WITH_COMMENT, start);
|
|
147
|
-
if (middle < 0) return input;
|
|
148
|
-
const middleEnd = middle + 17;
|
|
149
|
-
const end = input.indexOf(END_COMMENT, middleEnd);
|
|
150
|
-
if (end < 0) return input;
|
|
151
|
-
const endEnd = end + 16;
|
|
152
|
-
const before = input.slice(0, start);
|
|
153
|
-
const newText = input.slice(middleEnd, end).replaceAll(/^\s*\/\//gm, "");
|
|
154
|
-
const after = input.slice(endEnd);
|
|
155
|
-
input = before + newText + after;
|
|
156
|
-
start = input.indexOf(REPLACE_COMMENT, before.length + newText.length);
|
|
157
|
-
}
|
|
158
|
-
return input;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Removes magic comments without performing the TS to JS transform
|
|
162
|
-
* @param code Source coude
|
|
163
|
-
* @param fileName File name for the source
|
|
164
|
-
* @param prettierOptions Options to pass to prettier
|
|
165
|
-
*/
|
|
166
|
-
async function removeMagicComments(code, fileName, prettierOptions) {
|
|
167
|
-
const REPLACE_COMMENT = "// @detype: replace\n";
|
|
168
|
-
const WITH_COMMENT = "// @detype: with\n";
|
|
169
|
-
const END_COMMENT = "// @detype: end\n";
|
|
170
|
-
let start = code.indexOf(REPLACE_COMMENT);
|
|
171
|
-
let startEnd = start + 20;
|
|
172
|
-
while (start >= 0) {
|
|
173
|
-
const middle = code.indexOf(WITH_COMMENT, start);
|
|
174
|
-
if (middle < 0) return code;
|
|
175
|
-
const middleEnd = middle + 17;
|
|
176
|
-
const end = code.indexOf(END_COMMENT, middleEnd);
|
|
177
|
-
if (end < 0) return code;
|
|
178
|
-
const endEnd = end + 16;
|
|
179
|
-
const before = code.slice(0, start);
|
|
180
|
-
const keptText = code.slice(startEnd, middle);
|
|
181
|
-
const after = code.slice(endEnd);
|
|
182
|
-
code = before + keptText + after;
|
|
183
|
-
start = code.indexOf(REPLACE_COMMENT, before.length + keptText.length);
|
|
184
|
-
startEnd = start + 20;
|
|
185
|
-
}
|
|
186
|
-
code = await (0, prettier.format)(code, {
|
|
187
|
-
...prettierOptions,
|
|
188
|
-
filepath: fileName
|
|
189
|
-
});
|
|
190
|
-
return code;
|
|
191
|
-
}
|
|
192
|
-
//#endregion
|
|
193
|
-
//#region src/transformFile.ts
|
|
194
|
-
const { readFile, writeFile } = node_fs.default.promises;
|
|
195
|
-
/**
|
|
196
|
-
* Transform the input file and write the output to another file
|
|
197
|
-
* @param inputFileName
|
|
198
|
-
* @param outputFileName
|
|
199
|
-
*/
|
|
200
|
-
async function transformFile(inputFileName, outputFileName, options = {}) {
|
|
201
|
-
await writeFile(outputFileName, await transform(await readFile(inputFileName, "utf-8"), inputFileName, {
|
|
202
|
-
prettierOptions: await (0, prettier.resolveConfig)(inputFileName),
|
|
203
|
-
...options
|
|
204
|
-
}), "utf-8");
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Remove magic comments from the input file and write the output to another file
|
|
208
|
-
* @param inputFileName
|
|
209
|
-
* @param outputFileName
|
|
210
|
-
*/
|
|
211
|
-
async function removeMagicCommentsFromFile(inputFileName, outputFileName) {
|
|
212
|
-
await writeFile(outputFileName, await removeMagicComments(await readFile(inputFileName, "utf-8"), inputFileName, await (0, prettier.resolveConfig)(inputFileName)), "utf-8");
|
|
213
|
-
}
|
|
214
|
-
//#endregion
|
|
215
|
-
exports.removeMagicComments = removeMagicComments;
|
|
216
|
-
exports.removeMagicCommentsFromFile = removeMagicCommentsFromFile;
|
|
217
|
-
exports.transform = transform;
|
|
218
|
-
exports.transformFile = transformFile;
|
package/dist/index.d.cts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Options as PrettierOptions } from "prettier";
|
|
2
|
-
import { TransformOptions } from "@babel/core";
|
|
3
|
-
|
|
4
|
-
//#region src/transform.d.ts
|
|
5
|
-
interface RemoveTypeOptions {
|
|
6
|
-
/** Whether to remove ts-ignore and ts-expect-error comments */
|
|
7
|
-
removeTsComments?: boolean;
|
|
8
|
-
/** Escape hatch for customizing Babel configuration */
|
|
9
|
-
customizeBabelConfig?(config: TransformOptions): void;
|
|
10
|
-
}
|
|
11
|
-
interface TransformOptions$1 extends RemoveTypeOptions {
|
|
12
|
-
/** Prettier options */
|
|
13
|
-
prettierOptions?: PrettierOptions | null;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Transform TypeScript code into vanilla JavaScript without affecting the formatting
|
|
17
|
-
* @param code Source coude
|
|
18
|
-
* @param fileName File name for the source
|
|
19
|
-
* @param options Options
|
|
20
|
-
*/
|
|
21
|
-
declare function transform(code: string, fileName: string, options?: TransformOptions$1): Promise<string>;
|
|
22
|
-
/**
|
|
23
|
-
* Removes magic comments without performing the TS to JS transform
|
|
24
|
-
* @param code Source coude
|
|
25
|
-
* @param fileName File name for the source
|
|
26
|
-
* @param prettierOptions Options to pass to prettier
|
|
27
|
-
*/
|
|
28
|
-
declare function removeMagicComments(code: string, fileName: string, prettierOptions?: PrettierOptions | null): Promise<string>;
|
|
29
|
-
//#endregion
|
|
30
|
-
//#region src/transformFile.d.ts
|
|
31
|
-
/**
|
|
32
|
-
* Transform the input file and write the output to another file
|
|
33
|
-
* @param inputFileName
|
|
34
|
-
* @param outputFileName
|
|
35
|
-
*/
|
|
36
|
-
declare function transformFile(inputFileName: string, outputFileName: string, options?: RemoveTypeOptions): Promise<void>;
|
|
37
|
-
/**
|
|
38
|
-
* Remove magic comments from the input file and write the output to another file
|
|
39
|
-
* @param inputFileName
|
|
40
|
-
* @param outputFileName
|
|
41
|
-
*/
|
|
42
|
-
declare function removeMagicCommentsFromFile(inputFileName: string, outputFileName: string): Promise<void>;
|
|
43
|
-
//#endregion
|
|
44
|
-
export { type PrettierOptions, removeMagicComments, removeMagicCommentsFromFile, transform, transformFile };
|
package/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./dist";
|