@longzai-intelligence-oxlint/tsdoc-plugin 0.1.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/README.md +17 -0
- package/dist/configs/recommended.d.ts +10 -0
- package/dist/configs/recommended.js +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +16 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @longzai-intelligence-oxlint/tsdoc-plugin
|
|
2
|
+
|
|
3
|
+
## 意图
|
|
4
|
+
|
|
5
|
+
在静态检查阶段守护 TSDoc 注释规范,统一组织内的文档注释写法并拦截遗留 JSDoc 写法。
|
|
6
|
+
|
|
7
|
+
## 定位
|
|
8
|
+
|
|
9
|
+
Oxlint 生态的 TSDoc 治理插件,规则数量较多,是组织内文档注释治理的核心载体。
|
|
10
|
+
|
|
11
|
+
## 职能
|
|
12
|
+
|
|
13
|
+
提供共二十条规则,覆盖:禁用注释内代码、禁用 description 标签、禁用多余 param、禁用遗留 JSDoc 标签、禁用占位描述、param 连字符格式、标签前空行、deprecated 必备替代说明、description 必备、多行属性注释必备、param 必备、param 描述必备、returns 必备、returns 描述必备、throws 必备、throws 类型必备、tsdoc 必备、type param 必备、分隔符格式、TODO 格式等;使用 `defineRule` + `createOnce` 实现以获得最佳性能。
|
|
14
|
+
|
|
15
|
+
## 实现情况
|
|
16
|
+
|
|
17
|
+
二十条规则均已实现并按规则文件组织,统一注册为 `@longzai-intelligence/tsdoc`;规则集合稳定且覆盖 TSDoc 主要规范维度。
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={"@longzai-intelligence-oxlint/tsdoc-plugin/require-tsdoc":[`error`,{checkAllVariables:!0}],"@longzai-intelligence-oxlint/tsdoc-plugin/require-param":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-returns":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-description":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-param-description":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-returns-description":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-type-param":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/no-description-tag":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/param-hyphen-format":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-blank-line-before-tags":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/separator-format":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/todo-format":`warn`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-throws":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-throws-type":`warn`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-deprecated-alternative":`warn`,"@longzai-intelligence-oxlint/tsdoc-plugin/no-legacy-jsdoc-tags":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/no-placeholder-description":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/no-commented-code":`warn`,"@longzai-intelligence-oxlint/tsdoc-plugin/no-extra-param":`error`,"@longzai-intelligence-oxlint/tsdoc-plugin/require-multiline-property-comment":`error`};export{e as recommended};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Rule } from "@oxlint/plugins";
|
|
2
|
+
//#region src/index.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* tsdoc 规则集合
|
|
5
|
+
*/
|
|
6
|
+
declare const tsdocRules: Record<string, Rule>;
|
|
7
|
+
/**
|
|
8
|
+
* tsdoc 插件
|
|
9
|
+
*/
|
|
10
|
+
declare const tsdocPlugin: import("@oxlint/plugins").Plugin;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { tsdocPlugin as default, tsdocPlugin, tsdocRules };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";import*as n from"zod/mini";const r=[/^\s*(const|let|var)\s+\w+\s*=/,/^\s*function\s+\w+\s*\(/,/^\s*class\s+\w+/,/^\s*interface\s+\w+/,/^\s*type\s+\w+\s*=/,/^\s*enum\s+\w+/,/^\s*import\s+.*from\s+['"]/,/^\s*export\s+(default\s+)?(function|class|const|let|var|interface|type|enum)/,/^\s*return\s+/,/^\s*if\s*\(/,/^\s*for\s*\(/,/^\s*while\s*\(/,/^\s*switch\s*\(/,/^\s*try\s*\{/,/^\s*catch\s*\(/,/^\s*throw\s+/,/^\s*console\.(log|error|warn|info|debug)\s*\(/,/^\s*\w+\s*\(\s*\)\s*;?\s*$/];function i(e){let t=e.trim();if(t.length===0)return!1;for(let e of r)if(e.test(t))return!0;return!1}function a(e){let t=e.split(`
|
|
2
|
+
`),n=0,r=0;for(let e of t){let t=e.trim();t.length===0||t===`*`||(r++,i(t.replace(/^\*\s*/,``))&&n++)}return r>0&&n/r>=.5}function o(e){return i(e.trim())}const s=e({meta:{type:`suggestion`,docs:{description:`禁止注释掉的代码`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n)r.type===`Block`?a(r.value)&&e.report({node:t,message:`检测到注释掉的代码,请删除或恢复该代码`}):r.type===`Line`&&o(r.value)&&e.report({node:t,message:`检测到注释掉的代码,请删除或恢复该代码`})}}}}),c=new Map,l=1e3;function u(e){let t=e.match(/^\{([^}]*)\}\s*(\S+)?\s*(.*)/);if(t)return{type:t[1]??``,name:t[2]||``,description:t[3]||``};let n=e.match(/^(\S+)\s*(.*)/);return n?{name:n[1]??``,description:n[2]||``,type:``}:{name:``,description:``,type:``}}function ee(e){let t=e.match(/^\{([^}]*)\}\s*(.*)/);return t?{type:t[1]??``,description:t[2]||``}:{description:e,type:``}}function te(e){let t=e.match(/^\{@link\s+([^}]+)\}\s*(.*)/);return t?{type:(t[1]??``).trim(),description:t[2]||``}:{description:e,type:``}}function ne(e,t){if(e===`param`||e===`typeParam`||e===`template`){let n=u(t);return{tag:e,name:n.name,description:n.description,type:n.type}}if(e===`returns`||e===`return`){let n=ee(t);return{tag:e,name:``,description:n.description,type:n.type}}if(e===`throws`||e===`throw`){let n=te(t);return{tag:e,name:``,description:n.description,type:n.type}}return{tag:e,name:``,description:t,type:``}}function re(){if(c.size<=l)return;let e=Array.from(c.entries()).sort((e,t)=>e[1].lastAccess-t[1].lastAccess),t=e.slice(0,e.length-l);for(let[e]of t)c.delete(e)}function d(e){let t=c.get(e);if(t)return t.lastAccess=Date.now(),t.result;let n=ie(e);return c.set(e,{result:n,lastAccess:Date.now()}),re(),n}function ie(e){let t=e.trim();if(!t.startsWith(`*`))return null;let n=t.split(`
|
|
3
|
+
`),r=[],i=[],a=null,o=!0;for(let e=0;e<n.length;e++){let t=n[e];if(t)if(t=t.trim(),t.startsWith(`*`)&&(t=t.slice(1).trim()),t.startsWith(`@`)){o=!1,a&&i.push(a);let e=t.match(/^@(\w+)\s*(.*)/);if(e){let t=e[1];if(!t)continue;a=ne(t,e[2]??``)}}else o?(t||r.length>0)&&r.push(t):a&&(a.description+=(a.description?`
|
|
4
|
+
`:``)+t)}return a&&i.push(a),{description:r.join(`
|
|
5
|
+
`).trim(),tags:i}}function f(e){return e.tags.filter(e=>e.tag===`param`)}function p(e){return e.tags.find(e=>e.tag===`returns`||e.tag===`return`)}function m(e){return e.description.trim().length>0}function h(e){let t=e.description.trim();return!(t.length===0||t===`-`||t===`--`)}function g(e){return f(e).map(e=>e.name.split(`.`)[0]).filter(e=>typeof e==`string`)}const ae=e({meta:{type:`suggestion`,docs:{description:`禁止使用 description 标签`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);i&&i.tags.some(e=>e.tag===`description`)&&e.report({node:t,message:`请勿使用 description 标签,直接书写描述文本即可`})}}}}});n.object({type:n.string(),range:n.tuple([n.number(),n.number()])});const oe=n.object({init:n.unknown()}),se=n.object({type:n.string()});n.object({name:n.unknown()}),n.object({left:n.unknown(),right:n.unknown()}),n.object({id:n.object({name:n.string()})}),n.object({key:n.object({name:n.string()})}),n.object({declarations:n.array(n.object({id:n.optional(n.object({name:n.optional(n.string())}))}))}),n.object({type:n.literal(`ThrowStatement`),argument:n.unknown()}),n.object({type:n.literal(`NewExpression`),callee:n.unknown()}),n.object({type:n.literal(`Identifier`),name:n.unknown()}),n.object({consequent:n.array(n.unknown())}),n.object({consequent:n.unknown(),alternate:n.unknown()}),n.object({block:n.unknown(),handler:n.unknown()}),n.object({cases:n.unknown()}),n.object({body:n.array(n.unknown())});const ce=n.record(n.string(),n.unknown()),le=n.object({type:n.enum([`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`])});n.object({type:n.string(),params:n.array(n.unknown())});const ue=n.object({range:n.tuple([n.number(),n.number()])}),de=n.object({range:n.tuple([n.number(),n.number()])}),fe=n.object({range:n.tuple([n.number(),n.number()])}),pe=n.object({id:n.object({name:n.string()})}),me=n.object({key:n.object({name:n.string()})}),he=n.object({declarations:n.array(n.unknown())}),ge=n.object({typeParameters:n.object({params:n.array(n.record(n.string(),n.unknown()))})}),_e=n.object({params:n.array(n.unknown())}),ve=n.object({value:n.unknown()}),ye=n.object({declarations:n.array(n.unknown())});function _(e){return ue.safeParse(e).success}function be(e){return de.safeParse(e).success}function v(e){return fe.safeParse(e).success}function y(e){if(!_(e))return-1;if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(v(t))return t.range[0]}if(`parent`in e&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(_(t)&&`type`in t&&typeof t.type==`string`){if(t.type===`MethodDefinition`){if(`decorators`in t&&Array.isArray(t.decorators)&&t.decorators.length>0){let e=t.decorators[0];if(v(e))return e.range[0]}return t.range[0]}if(t.type===`Property`)return t.range[0];if(t.type===`VariableDeclarator`){let e=`parent`in t?t.parent:void 0;if(_(e)&&`type`in e&&typeof e.type==`string`&&e.type===`VariableDeclaration`){if(`parent`in e&&e.parent){let t=e.parent;if(_(t)&&`type`in t&&typeof t.type==`string`&&[`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type))return t.range[0]}return e.range[0]}}if([`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type))return t.range[0]}}return e.range[0]}function xe(e,t,n,r){let i=e.range[1],a=y(t);if(a<0)return!1;let o=n.filter(e=>e.range[0]>=i&&e.range[1]<=a),s=[];if(_(t)&&`decorators`in t){let e=t.decorators;if(Array.isArray(e))for(let t of e)v(t)&&s.push(t.range)}let c=[...o.map(e=>e.range),...s].sort((e,t)=>e[0]-t[0]),l=[],u=i;for(let e of c)e[0]>u&&l.push(r.slice(u,e[0])),u=Math.max(u,e[1]);u<a&&l.push(r.slice(u,a));for(let e of l)if(e.trim().length>0)return!1;return!0}function b(e,t,n){if(!be(t))return null;let r=y(t),i=r>=0?r:t.range[0],a=null;for(let t of e)t.type===`Block`&&t.value.startsWith(`*`)&&t.range[1]<=i&&(a===null||t.range[1]>a.range[1])&&(a={value:t.value,range:t.range});return a&&n&&!xe(a,t,e,n)?null:a}const x={description:`[待填写描述]`,functionDescription:`[待填写函数描述]`,methodDescription:`[待填写方法描述]`,classDescription:`[待填写类描述]`,variableDescription:`[待填写变量描述]`,paramDescription:`[待填写参数描述]`,returnsDescription:`[待填写返回值描述]`,typeParamDescription:`[待填写类型参数描述]`},Se=[/^\s*\*\s*描述\s*$/m,/^\s*\*\s*函数描述\s*$/m,/^\s*\*\s*方法描述\s*$/m,/^\s*\*\s*类描述\s*$/m,/^\s*\*\s*变量描述\s*$/m,/@param\s+\w+\s*-\s*参数描述/,/@returns\s+返回值描述/,/@typeParam\s+\w+\s*-\s*类型参数描述/];function Ce(e){return Object.values(x).some(t=>e.includes(t))?!0:Se.some(t=>t.test(e))}function S(e,t){let n=t[0];for(;n>0&&e[n-1]!==`
|
|
6
|
+
`;)n--;return e.slice(n,t[0])}function we(e,t,n,r){let i=`\n${r} * @param ${n} - ${x.paramDescription}`,a=t.value.match(/@param[^@]*$/);if(a&&a.index!==void 0){let n=t.range[0]+2+a.index+a[0].length;return e.insertTextAfterRange([t.range[0],n],i)}let o=t.range[1]-2;return e.insertTextBeforeRange([o,t.range[1]],i+`\n${r} `)}function Te(e,t,n){let r=`\n${n} * @returns ${x.returnsDescription}`,i=t.value.match(/@\w+[^@]*$/);if(i&&i.index!==void 0){let n=t.range[0]+2+i.index+i[0].length;return e.insertTextAfterRange([t.range[0],n],r)}let a=t.range[1]-2;return e.insertTextBeforeRange([a,t.range[1]],r+`\n${n} `)}function Ee(e,t,n,r){let i=`\n${r} * @typeParam ${n} - ${x.typeParamDescription}`,a=t.value,o=a.match(/@typeParam[^@]*$/);if(o&&o.index!==void 0){let n=t.range[0]+2+o.index+o[0].length;return e.insertTextAfterRange([t.range[0],n],i)}let s=a.match(/@param[^@]*$/);if(s&&s.index!==void 0)return e.insertTextBeforeRange([t.range[0]+2+s.index,t.range[1]],i+`
|
|
7
|
+
`+r+` *`);let c=t.range[1]-2;return e.insertTextBeforeRange([c,t.range[1]],i+`\n${r} `)}function De(e,t,n){let r=t.value;return r.trim()===`*`?e.replaceTextRange(t.range,`/**\n${n} * ${x.description}\n${n} */`):e.replaceTextRange(t.range,`/*${r}*/`)}function C(e,t){return e.slice(t).includes(`
|
|
8
|
+
`)?``:`
|
|
9
|
+
`}function Oe(e,t,n){let r=t.value,i=RegExp(`@param\\s+${w(n)}\\s*$`,`m`),a=i.exec(r);if(a){let o=C(r,a.index+a[0].length),s=r.replace(i,`@param ${n} - ${x.paramDescription}${o}`);return e.replaceTextRange(t.range,`/*${s}*/`)}return e.replaceTextRange(t.range,`/*${r}*/`)}function ke(e,t){let n=t.value,r=/@returns\s*$/m,i=r.exec(n);if(i){let a=C(n,i.index+i[0].length),o=n.replace(r,`@returns ${x.returnsDescription}${a}`);return e.replaceTextRange(t.range,`/*${o}*/`)}return e.replaceTextRange(t.range,`/*${n}*/`)}function w(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const T=n.object({name:n.optional(n.string())}),Ae=n.object({type:n.string(),name:n.optional(n.string()),left:n.optional(T),argument:n.optional(T),parameter:n.optional(T)});function je(e){return _e.safeParse(e).success}function E(e){return je(e)?e.params.map(e=>{let t=Ae.safeParse(e);if(!t.success)return``;let n=t.data;switch(n.type){case`Identifier`:return n.name??``;case`AssignmentPattern`:return n.left?.name??``;case`RestElement`:return n.argument?.name??``;case`ObjectPattern`:return Me(n)??`options`;case`ArrayPattern`:return`args`;case`TSParameterProperty`:return n.parameter?.name??``;default:return``}}).filter(e=>!!e):[]}function Me(e){return null}const Ne=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`禁止多余的 @param 标签`}},createOnce(e){let t=[];function n(n){let r=b(t,n,e.sourceCode.text);if(!r)return;let i=d(r.value);if(!i)return;let a=E(n),o=g(i).filter(e=>!a.includes(e));for(let t of o)e.report({node:n,message:`@param "${t}" 在函数签名中不存在`,fix:e=>{let n=r.value,i=RegExp(`\\n\\s*\\*\\s*@param\\s+${w(t)}\\b[^\\n]*`),a=n.replace(i,``);return e.replaceTextRange(r.range,`/*${a}*/`)}})}return{Program(){t=e.sourceCode.getAllComments()},FunctionDeclaration(e){n(e)},FunctionExpression(e){n(e)},ArrowFunctionExpression(e){if(`parent`in e&&e.parent){let t=e.parent.type;if(t===`CallExpression`||t===`Property`)return}n(e)}}}}),Pe=[`file`,`module`,`author`,`since`];function Fe(e){return Pe.includes(e)}function Ie(e,t,n,r){let i=e.split(`
|
|
10
|
+
`),a=-1;for(let e=0;e<i.length;e++){let n=i[e];if(n&&n.trim().startsWith(`* @${t}`)){a=e;break}}if(a===-1)return n.replaceTextRange(r,`/*${e}*/`);let o=i.filter((e,t)=>t!==a).join(`
|
|
11
|
+
`);return n.replaceTextRange(r,`/*${o}*/`)}const Le=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`禁止使用旧版 JSDoc 标签`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(i)for(let a of i.tags)Fe(a.tag)&&e.report({node:t,message:`禁止使用旧版 JSDoc 标签 @${a.tag},该标签在 TSDoc 中已不推荐使用`,fix:e=>Ie(n,a.tag,e,r.range)})}}}}}),Re=[...Object.values(x),`参数描述`,`返回值描述`,`函数描述`,`方法描述`,`类描述`,`变量描述`,`类型参数描述`,`描述`];function D(e){let t=e.trim();t.startsWith(`-`)&&(t=t.slice(1).trim());for(let e of Re)if(t===e)return e;return null}function ze(e){let t=D(e);return t?`禁止使用占位描述 "${t}",请提供有意义的描述`:null}function Be(e){let t=[],n=f(e);for(let e of n){let n=D(e.description);n&&t.push(`@param 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}let r=p(e);if(r){let e=D(r.description);e&&t.push(`@returns 标签禁止使用占位描述 "${e}",请提供有意义的描述`)}let i=e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`);for(let e of i){let n=D(e.description);n&&t.push(`@typeParam 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}return t}const Ve=e({meta:{type:`suggestion`,docs:{description:`禁止使用占位描述文本`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=ze(i.description);a&&e.report({node:t,message:a});let o=Be(i);for(let n of o)e.report({node:t,message:n})}}}}});function He(e){return e?e.trim().startsWith(`-`):!1}const Ue=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:"要求参数描述使用 `-` 分隔"}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=f(i);for(let i of a)He(i.description)||e.report({node:t,message:`参数 "${i.name}" 的描述应该使用 \`-\` 分隔,格式:@param ${i.name} - 描述`,fix:e=>{let t=RegExp(`(@param\\s+${w(i.name)}\\s+)([^\\-\\s].*?)(\\n|$)`,`g`),a=n.replace(t,`$1- $2$3`);return e.replaceTextRange(r.range,`/*${a}*/`)}})}}}}});function We(e){let t=e.split(`
|
|
12
|
+
`),n=-1;for(let e=0;e<t.length;e++){let r=t[e];if(!r)continue;let i=r.trim();if(i.startsWith(`*`)&&i.slice(1).trim().startsWith(`@`)){n=e;break}}if(n===-1||n===0)return!0;let r=t[n-1];if(!r)return!0;let i=r.trim();return i===`*`||i===``}const Ge=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求标签前有空行`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);i&&i.tags.length>0&&m(i)&&(We(n)||e.report({node:t,message:`标签前应有一个空行`,fix:e=>{let t=n.replace(/(\* [^\n@]+)\n(\s*\* @)/g,`$1
|
|
13
|
+
*
|
|
14
|
+
$2`);return e.replaceTextRange(r.range,`/*${t}*/`)}}))}}}}}),Ke=[/使用\s+\S+\s+代替/,/请使用\s+\S+/,/use\s+\S+\s+instead/i,/replaced\s+by\s+\S+/i];function qe(e){if(!e)return!1;let t=e.trim();if(t.length===0)return!1;for(let e of Ke)if(e.test(t))return!0;return t.length>10}const Je=e({meta:{type:`suggestion`,docs:{description:`要求 @deprecated 标签有替代方案说明`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=i.tags.find(e=>e.tag===`deprecated`);a&&(qe(a.description)||e.report({node:t,message:`@deprecated 标签应该包含替代方案说明,例如:@deprecated 使用 newMethod 代替`}))}}}}}),Ye=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`ClassDeclaration`,`VariableDeclaration`,`MethodDefinition`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`],Xe=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 TSDoc 注释有描述文本`}},createOnce(e){let t=[];function n(n){let r=b(t,n,e.sourceCode.text);if(!r)return;let i=d(r.value);i&&(m(i)||e.report({node:n,message:`TSDoc 注释缺少描述`,fix:t=>{let n=S(e.sourceCode.text,r.range);return De(t,r,n)}}))}let r={Program(){t=e.sourceCode.getAllComments()}};for(let e of Ye)r[e]=e=>n(e);return r}});function O(e){return pe.safeParse(e).success}function k(e){return me.safeParse(e).success}function A(e){return he.safeParse(e).success}function Ze(e){if(!Array.isArray(e)||e.length===0)return null;let t=e[0];if(!t||typeof t!=`object`)return null;let n=t;if(`type`in n&&n.type===`Property`&&`key`in n){let e=n.key;if(e&&typeof e==`object`&&`name`in e&&typeof e.name==`string`)return e.name}if(`type`in n&&n.type===`RestElement`&&`argument`in n){let e=n.argument;if(e&&typeof e==`object`&&`name`in e&&typeof e.name==`string`)return e.name}return null}function Qe(e){if(!Array.isArray(e)||e.length===0)return null;let t=e[0];return t&&typeof t==`object`&&`name`in t&&typeof t.name==`string`?t.name:null}function $e(e){if(!e||typeof e!=`object`)return null;let t=e;return`type`in t&&t.type===`ObjectPattern`&&`properties`in t?Ze(t.properties):`type`in t&&t.type===`ArrayPattern`&&`elements`in t?Qe(t.elements):null}function et(e){if(!A(e)||e.declarations.length===0)return null;let t=e.declarations[0];if(!t||typeof t!=`object`||!t||!(`id`in t)||!t.id)return null;let n=t.id;if(typeof n==`object`&&`type`in n){let e=n;if(e.type===`Identifier`&&`name`in e)return typeof e.name==`string`?e.name:null;if(e.type===`ObjectPattern`||e.type===`ArrayPattern`)return $e(n)}return O(t)?t.id?.name??null:null}function j(e){if(!e||typeof e!=`object`||!(`type`in e))return null;let t=e.type;if(typeof t!=`string`)return null;switch(t){case`FunctionDeclaration`:case`ClassDeclaration`:case`TSInterfaceDeclaration`:case`TSTypeAliasDeclaration`:case`TSEnumDeclaration`:case`TSEnumMember`:return O(e)?e.id?.name??null:null;case`MethodDefinition`:case`PropertyDefinition`:case`TSPropertySignature`:return k(e)?e.key?.name??null:null;case`VariableDeclaration`:return et(e);default:return null}}const tt={FunctionDeclaration:`函数`,MethodDefinition:`方法`,ClassDeclaration:`类`,VariableDeclaration:`变量`,TSInterfaceDeclaration:`接口`,TSTypeAliasDeclaration:`类型别名`,TSEnumDeclaration:`枚举`,PropertyDefinition:`类属性`,TSPropertySignature:`接口属性`,TSEnumMember:`枚举成员`};function M(e){return tt[e]||e}function N(e){return ge.safeParse(e).success}function nt(e){return N(e)?e.typeParameters.params.map(e=>e.name&&typeof e.name==`object`&&`name`in e.name?String(e.name.name):``).filter(Boolean):[]}function rt(e){return!e.trim().includes(`
|
|
15
|
+
`)}function it(e){return k(e)?e.key.name:O(e)?e.id.name:`(匿名)`}const at=e({meta:{type:`suggestion`,docs:{description:`要求接口属性、类属性、枚举成员使用多行 TSDoc 注释格式`}},createOnce(e){return{TSPropertySignature(t){P(t,e)},PropertyDefinition(t){P(t,e)},TSEnumMember(t){P(t,e)}}}});function P(e,t){let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=n.value;if(rt(r)){let n=it(e);t.report({node:e,message:`"${n}"的注释应使用多行 TSDoc 格式,当前为单行格式`})}}const ot=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 @param 标签有描述`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=f(i);for(let n of a)h(n)||e.report({node:t,message:`参数 "${n.name}" 缺少描述`,fix:e=>Oe(e,r,n.name)})}}}}}),st=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求函数参数有 @param 标签`}},createOnce(e){let t=[];function n(n){let r=b(t,n,e.sourceCode.text);if(!r)return;let i=E(n);if(i.length===0)return;let a=d(r.value);if(!a)return;let o=g(a),s=i.filter(e=>!o.includes(e));for(let t of s)e.report({node:n,message:`参数 "${t}" 缺少 @param 标签`,fix:n=>{let i=S(e.sourceCode.text,r.range);return we(n,r,t,i)}})}return{Program(){t=e.sourceCode.getAllComments()},FunctionDeclaration(e){n(e)},FunctionExpression(e){n(e)},ArrowFunctionExpression(e){if(`parent`in e&&e.parent){let t=e.parent.type;if(t===`CallExpression`||t===`Property`)return}n(e)}}}}),ct=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 @returns 标签有描述`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=p(i);a&&!h(a)&&e.report({node:t,message:`@returns 标签缺少描述`,fix:e=>ke(e,r)})}}}}});function F(e){return typeof e!=`object`||!e||!(`type`in e)?!1:typeof e.type==`string`}function lt(e){return F(e)&&e.type===`ReturnStatement`&&`argument`in e}function ut(e){return typeof e==`object`&&!!e&&`body`in e}function dt(e){return typeof e==`object`&&!!e&&`returnType`in e}function ft(e){return F(e)?[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`].includes(e.type):!1}function I(e,t){if(!e||typeof e!=`object`)return!1;let n=e;if(t.has(n))return!1;if(t.add(n),lt(n))return!0;if(ft(n))return!1;for(let e of Object.keys(n)){let r=Object.getOwnPropertyDescriptor(n,e);if(!r||!(`value`in r))continue;let i=r.value;if(i&&typeof i==`object`){if(Array.isArray(i)){for(let e of i)if(I(e,t))return!0}else if(`type`in i&&I(i,t))return!0}}return!1}function L(e){if(typeof e!=`object`||!e||!ut(e)||!e.body)return!1;let t=e.body;return typeof t!=`object`||!t?!1:!(`type`in t)||t.type!==`BlockStatement`||I(t,new WeakSet)}function R(e){if(typeof e!=`object`||!e||!dt(e)||!e.returnType)return!1;let t=e.returnType;if(!t||typeof t!=`object`||!(`typeAnnotation`in t)||!t.typeAnnotation)return!1;let n=t.typeAnnotation;if(typeof n!=`object`||!(`type`in n))return!1;if(n.type===`TSVoidKeyword`)return!0;if(n.type===`TSTypeReference`){let e=`typeName`in n?n.typeName:null;if(e&&typeof e==`object`&&`name`in e&&e.name===`Promise`){let e=`typeArguments`in n?n.typeArguments:null;if(e&&typeof e==`object`&&`params`in e&&Array.isArray(e.params)&&e.params.length>0){let t=e.params[0];if(F(t))return t.type===`TSVoidKeyword`}}}return!1}function pt(e){return L(e)?!R(e):!1}const mt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求有返回值的函数有 @returns 标签`}},createOnce(e){return{FunctionDeclaration(t){z(t,e)},FunctionExpression(t){z(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}z(t,e)}}}});function z(e,t){if(!pt(e))return;let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=d(n.value);r&&(p(r)||t.report({node:e,message:`缺少 @returns 文档`,fix:e=>{let r=S(t.sourceCode.text,n.range);return Te(e,n,r)}}))}function ht(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&`range`in t&&Array.isArray(t.range)}const gt=e({meta:{type:`suggestion`,docs:{description:`要求 @throws 标签有异常类型`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let t of n){if(t.type!==`Block`)continue;let n=t.value;if(!n.startsWith(`*`))continue;let r=d(n);if(!r)continue;let i=r.tags.filter(e=>e.tag===`throws`||e.tag===`throw`);for(let n of i)!n.type&&ht(t)&&e.report({node:t,message:`@throws 标签应使用 {@link Type} 格式声明异常类型,例如:@throws {@link Error} 描述`})}}}}});function B(e){if(typeof e!=`object`||!e)return!1;let t=e;return`body`in t&&Array.isArray(t.body)}function _t(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`ThrowStatement`&&`argument`in t}function vt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`NewExpression`&&`callee`in t}function V(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`Identifier`&&`name`in t}function yt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`consequent`in t&&`alternate`in t}function bt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`block`in t&&`handler`in t}function xt(e){return typeof e!=`object`||!e?!1:`cases`in e}function St(e){if(typeof e!=`object`||!e||!(`consequent`in e))return!1;let t=e;return Array.isArray(t.consequent)}function Ct(e){let t=e.argument;if(vt(t)){let e=t.callee;if(V(e))return e.name}return V(t)?t.name:`Error`}function H(e,t){if(!B(e))return;let n=e;if(Array.isArray(n.body))for(let e of n.body)U(e,t)}function U(e,t){if(!e||typeof e!=`object`)return;let n=e;if(`type`in n&&n.type===`ThrowStatement`&&_t(n)){let e=Ct(n);t.push({typeName:e});return}if(`type`in n&&n.type===`IfStatement`&&yt(n)){U(n.consequent,t),n.alternate&&U(n.alternate,t);return}if(`type`in n&&n.type===`TryStatement`&&bt(n)){wt(n,t);return}if(`type`in n&&n.type===`SwitchStatement`&&xt(n)){Tt(n,t);return}`type`in n&&n.type===`BlockStatement`&&B(n)&&H(n,t)}function wt(e,t){B(e.block)&&H(e.block,t),e.handler&&typeof e.handler==`object`&&`body`in e.handler&&e.handler.body&&B(e.handler.body)&&H(e.handler.body,t)}function Tt(e,t){for(let n of e.cases)if(St(n))for(let e of n.consequent)U(e,t)}function Et(e){if(!e||typeof e!=`object`||!(`body`in e)||!e.body)return[];let t=e.body;if(typeof t!=`object`||!t||!(`type`in t)||t.type!==`BlockStatement`)return[];let n=[];return H(t,n),n}const Dt=e({meta:{type:`suggestion`,docs:{description:`要求抛出异常的函数有 @throws 标签`}},createOnce(e){return{FunctionDeclaration(t){W(t,e)},FunctionExpression(t){W(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}W(t,e)}}}});function W(e,t){let n=Et(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r){G(e,t,n);return}let i=d(r.value);if(!i){G(e,t,n);return}i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`).length===0&&G(e,t,n)}function G(e,t,n){let r=[...new Set(n.map(e=>e.typeName))],i=r[0]||`Error`;t.report({node:e,message:`函数抛出异常但没有 @throws 标签。抛出的异常类型: ${r.join(`, `)}。正确用法: @throws {@link ${i}} 异常描述`})}function Ot(e){return le.safeParse(e).success}function kt(e){return ce.safeParse(e).success}function At(e){return oe.safeParse(e).success}function jt(e){return se.safeParse(e).success}function Mt(e){return ve.safeParse(e).success}function Nt(e){return ye.safeParse(e).success}function Pt(e,t){return e.type===`FunctionDeclaration`||e.type===`FunctionExpression`||e.type===`ArrowFunctionExpression`?Ft(e,t):e.type===`MethodDefinition`&&Mt(e)&&e.value?It(e.value,t):e.type===`ClassDeclaration`?Lt(t):e.type===`VariableDeclaration`&&Nt(e)?Rt(e.declarations,t):K(t)}function Ft(e,t){let n=E(e),r=L(e),i=R(e),a=[];a.push(`/**`),a.push(` * ${x.functionDescription}`);for(let e of n)a.push(` * @param ${e} - ${x.paramDescription}`);return r&&!i&&a.push(` * @returns ${x.returnsDescription}`),a.push(` */`),`\n${t}`+a.join(`\n${t}`)+`\n${t}`}function It(e,t){if(!e||typeof e!=`object`||!Ot(e))return K(t);let n=e,r=E(n),i=L(n),a=R(n),o=[];o.push(`/**`),o.push(` * ${x.methodDescription}`);for(let e of r)o.push(` * @param ${e} - ${x.paramDescription}`);return i&&!a&&o.push(` * @returns ${x.returnsDescription}`),o.push(` */`),`\n${t}`+o.join(`\n${t}`)+`\n${t}`}function Lt(e){let t=[];return t.push(`/**`),t.push(` * ${x.classDescription}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function Rt(e,t){let n=e[0];if(!n||!kt(n))return K(t);let r=At(n)?n.init:void 0;if(r&&typeof r==`object`&&jt(r)){let e=r.type;if(e===`ArrowFunctionExpression`||e===`FunctionExpression`)return K(t)}let i=[];return i.push(`/**`),i.push(` * ${x.variableDescription}`),i.push(` */`),`\n${t}`+i.join(`\n${t}`)+`\n${t}`}function K(e){let t=[];return t.push(`/**`),t.push(` * ${x.description}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function q(e){return typeof e==`object`&&!!e&&`type`in e&&typeof e.type==`string`}function J(e){return typeof e==`object`&&!!e&&`parent`in e}function zt(e){return typeof e==`object`&&!!e&&`init`in e}function Y(e){return typeof e==`object`&&!!e}const Bt=[`FunctionDeclaration`,`MethodDefinition`,`ClassDeclaration`,`VariableDeclaration`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSEnumMember`];function Vt(e){if(!Y(e)||e.type!==`TSPropertySignature`)return!1;let t=e.key;return Y(t)&&t.type===`Identifier`&&`name`in t&&typeof t.name==`string`?t.name===`null`||t.name===`undefined`:!1}function Ht(e,t){if(J(e)&&e.parent&&typeof e.parent==`object`&&q(e.parent)&&[`ForStatement`,`ForInStatement`,`ForOfStatement`].includes(e.parent.type))return!0;if(e.type===`VariableDeclaration`){if(t)return!1;if(A(e)&&e.declarations.length>0){let t=e.declarations[0];if(!t)return!0;if(zt(t)&&t.init&&typeof t.init==`object`&&q(t.init)&&(t.init.type===`ArrowFunctionExpression`||t.init.type===`FunctionExpression`))return!1}return!0}return!!Vt(e)}function Ut(e){return e.includes(`/**`)}function Wt(e){if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(Y(t)){let e=t.range;if(Array.isArray(e)&&e.length>=1&&typeof e[0]==`number`)return[e[0],e[0]]}}if(J(e)&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(q(t)&&Y(t)&&[`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type)){let e=t.range;if(Array.isArray(e)&&e.length>=1&&typeof e[0]==`number`)return[e[0],e[0]]}}return[e.range[0],e.range[0]]}function Gt(e,t){if(!e)return``;let n=t;for(;n>0&&e[n-1]!==`
|
|
16
|
+
`;)n--;return e.slice(n,t)}function Kt(e,t,n){if(t.skipFile||Ht(e,t.checkAllVariables))return;let r=b(t.commentsCache,e,n.sourceCode.text);if(!r){let t=M(e.type),r=j(e);n.report({node:e,message:`${t}"${r}"缺少 TSDoc 注释`,fix:t=>{let r=Wt(e),i=Pt(e,Gt(n.sourceCode.text,r[0]));return t.insertTextBeforeRange(r,i)}});return}let i=r.value;if(Ce(i)){let t=M(e.type),r=j(e);n.report({node:e,message:`${t}"${r}"的 TSDoc 注释包含占位描述,请填写实际描述`})}}function qt(e,t){let n=e.getAllComments(),r=e.text;if(r!=null){if(!Ut(r))return t.skipFile=!0,n}else if(!n.some(e=>e.type===`Block`&&e.value.startsWith(`*`)))return t.skipFile=!0,n;return n}function Jt(e){if(typeof e==`object`&&e&&!Array.isArray(e)){let t=e;if(`checkAllVariables`in t&&typeof t.checkAllVariables==`boolean`)return t.checkAllVariables}return!1}const Yt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 TSDoc 注释存在`},schema:[{type:`object`,properties:{contexts:{type:`array`,items:{type:`string`}},checkAllVariables:{type:`boolean`}},additionalProperties:!1}]},createOnce(e){let t={commentsCache:[],checkAllVariables:!1,skipFile:!1},n={Program(n){t.skipFile=!1,t.checkAllVariables=!1,t.commentsCache=qt(e.sourceCode,t);let r=e.options?.[0];t.checkAllVariables=Jt(r)}};for(let r of Bt)n[r]=n=>Kt(n,t,e);return n}});function Xt(e){return e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`).map(e=>e.name)}const X=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求泛型有 @typeParam 标签`}},createOnce(e){return{FunctionDeclaration(t){Z(t,e)},FunctionExpression(t){Z(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}Z(t,e)},ClassDeclaration(t){Z(t,e)},TSInterfaceDeclaration(t){Z(t,e)},TSTypeAliasDeclaration(t){Z(t,e)}}}});function Z(e,t){if(!N(e))return;let n=nt(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r)return;let i=d(r.value);if(!i)return;let a=Xt(i),o=n.filter(e=>!a.includes(e));for(let n of o)t.report({node:e,message:`缺少类型参数 "${n}" 的 @typeParam 文档`,fix:e=>{let i=S(t.sourceCode.text,r.range);return Ee(e,r,n,i)}})}const Zt=/^(=+)\s+(.+?)\s+(=+)$/;function Qt(e){let t=e.trim().match(Zt);return t?{leadingEquals:t[1]??``,text:t[2]??``,trailingEquals:t[3]??``}:null}const $t=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求代码块分隔符使用规范格式`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Line`)continue;let n=Qt(r.value.trim());if(n&&(n.leadingEquals.length!==20||n.trailingEquals.length!==20)){let i=`=`.repeat(20);e.report({node:t,message:`代码块分隔符格式不正确,应为:// ${i} ${n.text} ${i}`,fix:e=>{let t=`// ${i} ${n.text} ${i}`;return e.replaceTextRange(r.range,t)}})}}}}}}),en=/\bTODO(?:\(([^)]+)\))?:?\s*(.*)/i;function tn(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const nn={requireAuthor:!1,requireDescription:!0};function rn(e){return/\bTODO\b/i.test(e)}function an(e){let t={...nn};if(tn(e)){let n=e;typeof n.requireAuthor==`boolean`&&(t.requireAuthor=n.requireAuthor),typeof n.requireDescription==`boolean`&&(t.requireDescription=n.requireDescription)}return t}function on(e){let t=e.match(en);return t?{author:t[1]??``,description:(t[2]??``).trim()}:null}const Q={"no-commented-code":s,"no-description-tag":ae,"no-extra-param":Ne,"no-legacy-jsdoc-tags":Le,"no-placeholder-description":Ve,"param-hyphen-format":Ue,"require-blank-line-before-tags":Ge,"require-deprecated-alternative":Je,"require-description":Xe,"require-multiline-property-comment":at,"require-param":st,"require-param-description":ot,"require-returns":mt,"require-returns-description":ct,"require-throws":Dt,"require-throws-type":gt,"require-tsdoc":Yt,"require-type-param":X,"separator-format":$t,"todo-format":e({meta:{type:`suggestion`,docs:{description:`要求 TODO 注释有描述和作者`}},createOnce(e){let t=an(e.options?.[0]);return{Program(n){let r=e.sourceCode.getAllComments();for(let i of r){let r=i.value;if(!rn(r))continue;let a=on(r);a&&(t.requireAuthor&&!a.author&&e.report({node:n,message:`TODO 注释缺少作者信息,格式:TODO(author): 描述`}),t.requireDescription&&!a.description&&e.report({node:n,message:`TODO 注释缺少描述说明`}))}}}}})},$=t({meta:{name:`@longzai-intelligence-oxlint/tsdoc-plugin`},rules:Q});export{$ as default,$ as tsdocPlugin,Q as tsdocRules};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@longzai-intelligence-oxlint/tsdoc-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Oxlint TSDoc 插件,提供 TSDoc 注释规范检查规则",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./configs/recommended": {
|
|
18
|
+
"types": "./dist/configs/recommended.d.ts",
|
|
19
|
+
"import": "./dist/configs/recommended.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "lzi-builder",
|
|
24
|
+
"build:prod": "NODE_ENV=production lzi-builder",
|
|
25
|
+
"prepublishOnly": "bun run build:prod",
|
|
26
|
+
"dev": "lzi-builder --watch",
|
|
27
|
+
"clean": "rimraf dist",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"test:coverage": "vitest run --coverage",
|
|
31
|
+
"lint": "oxlint && oxfmt --check",
|
|
32
|
+
"lint:fix": "oxlint --fix && oxfmt",
|
|
33
|
+
"typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
|
|
34
|
+
"typecheck:app": "tsgo --noEmit -p tsconfig/app.json",
|
|
35
|
+
"typecheck:node": "tsgo --noEmit -p tsconfig/node.json",
|
|
36
|
+
"typecheck:test": "tsgo --noEmit -p tsconfig/test.json"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@longzai-intelligence-oxlint/core": "0.1.0",
|
|
40
|
+
"@longzai-intelligence-logger/node": "^0.1.1",
|
|
41
|
+
"@oxlint/plugins": "^1.74.0",
|
|
42
|
+
"zod": "^4.4.3"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
46
|
+
"acorn": "^8.17.0",
|
|
47
|
+
"typescript": "^6.0.3"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"oxlint": ">=1.0.0"
|
|
51
|
+
}
|
|
52
|
+
}
|