@longzai-intelligence/oxlint-plugin-tsdoc 0.0.1
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/dist/configs/recommended.cjs +1 -0
- package/dist/configs/recommended.d.cts +6 -0
- package/dist/configs/recommended.d.mts +6 -0
- package/dist/configs/recommended.mjs +1 -0
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +7 -0
- package/package.json +89 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e={"@longzai-intelligence/tsdoc/require-tsdoc":[`error`,{checkAllVariables:!0}],"@longzai-intelligence/tsdoc/require-param":`error`,"@longzai-intelligence/tsdoc/require-returns":`error`,"@longzai-intelligence/tsdoc/require-description":`error`,"@longzai-intelligence/tsdoc/require-param-description":`error`,"@longzai-intelligence/tsdoc/require-returns-description":`error`,"@longzai-intelligence/tsdoc/require-type-param":`error`,"@longzai-intelligence/tsdoc/no-description-tag":`error`,"@longzai-intelligence/tsdoc/param-hyphen-format":`error`,"@longzai-intelligence/tsdoc/require-blank-line-before-tags":`error`,"@longzai-intelligence/tsdoc/separator-format":`error`,"@longzai-intelligence/tsdoc/todo-format":`warn`,"@longzai-intelligence/tsdoc/require-throws":`error`,"@longzai-intelligence/tsdoc/require-throws-type":`warn`,"@longzai-intelligence/tsdoc/require-deprecated-alternative":`warn`,"@longzai-intelligence/tsdoc/no-legacy-jsdoc-tags":`error`,"@longzai-intelligence/tsdoc/no-placeholder-description":`error`,"@longzai-intelligence/tsdoc/no-commented-code":`warn`,"@longzai-intelligence/tsdoc/require-multiline-property-comment":`error`};exports.recommended=e;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e={"@longzai-intelligence/tsdoc/require-tsdoc":[`error`,{checkAllVariables:!0}],"@longzai-intelligence/tsdoc/require-param":`error`,"@longzai-intelligence/tsdoc/require-returns":`error`,"@longzai-intelligence/tsdoc/require-description":`error`,"@longzai-intelligence/tsdoc/require-param-description":`error`,"@longzai-intelligence/tsdoc/require-returns-description":`error`,"@longzai-intelligence/tsdoc/require-type-param":`error`,"@longzai-intelligence/tsdoc/no-description-tag":`error`,"@longzai-intelligence/tsdoc/param-hyphen-format":`error`,"@longzai-intelligence/tsdoc/require-blank-line-before-tags":`error`,"@longzai-intelligence/tsdoc/separator-format":`error`,"@longzai-intelligence/tsdoc/todo-format":`warn`,"@longzai-intelligence/tsdoc/require-throws":`error`,"@longzai-intelligence/tsdoc/require-throws-type":`warn`,"@longzai-intelligence/tsdoc/require-deprecated-alternative":`warn`,"@longzai-intelligence/tsdoc/no-legacy-jsdoc-tags":`error`,"@longzai-intelligence/tsdoc/no-placeholder-description":`error`,"@longzai-intelligence/tsdoc/no-commented-code":`warn`,"@longzai-intelligence/tsdoc/require-multiline-property-comment":`error`};export{e as recommended};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require(`@oxlint/plugins`);const t=[/^\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 n(e){let n=e.trim();if(n.length===0)return!1;for(let e of t)if(e.test(n))return!0;return!1}function r(e){let t=e.split(`
|
|
2
|
+
`),r=0,i=0;for(let e of t){let t=e.trim();t.length===0||t===`*`||(i++,n(t.replace(/^\*\s*/,``))&&r++)}return i>0&&r/i>=.5}function i(e){return n(e.trim())}const a=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`禁止注释掉的代码`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let a of n)a.type===`Block`?r(a.value)&&e.report({node:t,message:`检测到注释掉的代码,请删除或恢复该代码`}):a.type===`Line`&&i(a.value)&&e.report({node:t,message:`检测到注释掉的代码,请删除或恢复该代码`})}}}}),o=new Map,s=1e3;function c(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 l(e){let t=e.match(/^\{([^}]*)\}\s*(.*)/);return t?{type:t[1]??``,description:t[2]||``}:{description:e,type:``}}function u(e){let t=e.match(/^\{@link\s+([^}]+)\}\s*(.*)/);return t?{type:(t[1]??``).trim(),description:t[2]||``}:{description:e,type:``}}function d(e,t){if(e===`param`||e===`typeParam`||e===`template`){let n=c(t);return{tag:e,name:n.name,description:n.description,type:n.type}}if(e===`returns`||e===`return`){let n=l(t);return{tag:e,name:``,description:n.description,type:n.type}}if(e===`throws`||e===`throw`){let n=u(t);return{tag:e,name:``,description:n.description,type:n.type}}return{tag:e,name:``,description:t,type:``}}function ee(){if(o.size<=s)return;let e=Array.from(o.entries()).sort((e,t)=>e[1].lastAccess-t[1].lastAccess),t=e.slice(0,e.length-s);for(let[e]of t)o.delete(e)}function f(e){let t=o.get(e);if(t)return t.lastAccess=Date.now(),t.result;let n=te(e);return o.set(e,{result:n,lastAccess:Date.now()}),ee(),n}function te(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=d(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 p(e){return e.tags.filter(e=>e.tag===`param`)}function m(e){return e.tags.find(e=>e.tag===`returns`||e.tag===`return`)}function h(e){return e.description.trim().length>0}function g(e){let t=e.description.trim();return!(t.length===0||t===`-`||t===`--`)}function ne(e){return p(e).map(e=>e.name.split(`.`)[0]).filter(e=>typeof e==`string`)}const re=(0,e.defineRule)({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=f(n);i&&i.tags.some(e=>e.tag===`description`)&&e.report({node:t,message:`请勿使用 description 标签,直接书写描述文本即可`})}}}}}),ie=[`file`,`module`,`author`,`since`];function ae(e){return ie.includes(e)}const _=(0,e.defineRule)({meta:{type:`suggestion`,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=f(n);if(i)for(let n of i.tags)ae(n.tag)&&e.report({node:t,message:`禁止使用旧版 JSDoc 标签 @${n.tag},该标签在 TSDoc 中已不推荐使用`})}}}}}),v=[`参数描述`,`返回值描述`,`函数描述`,`方法描述`,`类描述`,`变量描述`,`类型参数描述`,`描述`];function y(e){let t=e.trim();t.startsWith(`-`)&&(t=t.slice(1).trim());for(let e of v)if(t===e)return e;return null}function b(e){let t=y(e);return t?`禁止使用占位描述 "${t}",请提供有意义的描述`:null}function x(e){let t=[],n=p(e);for(let e of n){let n=y(e.description);n&&t.push(`@param 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}let r=m(e);if(r){let e=y(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=y(e.description);n&&t.push(`@typeParam 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}return t}const oe=(0,e.defineRule)({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=f(n);if(!i)continue;let a=b(i.description);a&&e.report({node:t,message:a});let o=x(i);for(let n of o)e.report({node:t,message:n})}}}}});function se(e){return e?e.trim().startsWith(`-`):!1}const ce=(0,e.defineRule)({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=f(n);if(!i)continue;let a=p(i);for(let n of a)se(n.description)||e.report({node:t,message:`参数 "${n.name}" 的描述应该使用 \`-\` 分隔,格式:@param ${n.name} - 描述`})}}}}});function le(e){let t=e.split(`
|
|
6
|
+
`),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 ue=(0,e.defineRule)({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=f(n);i&&i.tags.length>0&&h(i)&&(le(n)||e.report({node:t,message:`标签前应有一个空行`}))}}}}}),de=[/使用\s+\S+\s+代替/,/请使用\s+\S+/,/use\s+\S+\s+instead/i,/replaced\s+by\s+\S+/i];function fe(e){if(!e)return!1;let t=e.trim();if(t.length===0)return!1;for(let e of de)if(e.test(t))return!0;return t.length>10}const pe=(0,e.defineRule)({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=f(n);if(!i)continue;let a=i.tags.find(e=>e.tag===`deprecated`);a&&(fe(a.description)||e.report({node:t,message:`@deprecated 标签应该包含替代方案说明,例如:@deprecated 使用 newMethod 代替`}))}}}}});function S(e){if(typeof e!=`object`||!e)return!1;let t=e;return`range`in t&&Array.isArray(t.range)&&t.range.length===2}function C(e){return S(e)}function w(e){return S(e)}function T(e){if(!C(e)||!e.range)return-1;if(!S(e))return e.range[0];if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(w(t)&&t.range)return t.range[0]}if(`parent`in e&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(S(t)&&`type`in t&&typeof t.type==`string`&&[`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type)&&t.range)return t.range[0]}return e.range[0]}function me(e,t,n,r){let i=e.range[1],a=T(t);if(a<0)return!1;let o=n.filter(e=>e.range[0]>=i&&e.range[1]<=a),s=[];if(S(t)&&`decorators`in t){let e=t.decorators;if(Array.isArray(e))for(let t of e)w(t)&&t.range&&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 E(e,t,n){if(!C(t)||!t.range)return null;let r=T(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&&!me(a,t,e,n)?null:a}const he=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`ClassDeclaration`,`VariableDeclaration`,`MethodDefinition`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`],ge=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求 TSDoc 注释有描述文本`}},createOnce(e){let t=[];function n(n){let r=E(t,n);if(!r)return;let i=f(r.value);i&&(h(i)||e.report({node:n,message:`TSDoc 注释缺少描述`}))}let r={Program(){t=e.sourceCode.getAllComments()}};for(let e of he)r[e]=e=>n(e);return r}});function D(e){if(typeof e!=`object`||!e)return!1;let t=e;if(!(`id`in t))return!1;let n=t.id;return typeof n!=`object`||!n?!1:`name`in n}function O(e){if(typeof e!=`object`||!e)return!1;let t=e;if(!(`key`in t))return!1;let n=t.key;return typeof n!=`object`||!n?!1:`name`in n}function k(e){if(typeof e!=`object`||!e)return!1;let t=e;return`declarations`in t?Array.isArray(t.declarations):!1}function A(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 j(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 M(e){if(!e||typeof e!=`object`)return null;let t=e;return`type`in t&&t.type===`ObjectPattern`&&`properties`in t?A(t.properties):`type`in t&&t.type===`ArrayPattern`&&`elements`in t?j(t.elements):null}function N(e){if(!k(e)||!e.declarations||e.declarations.length===0)return null;let t=e.declarations[0];if(!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 M(n)}return D(t)?t.id?.name??null:null}function P(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 D(e)?e.id?.name??null:null;case`MethodDefinition`:case`PropertyDefinition`:case`TSPropertySignature`:return O(e)?e.key?.name??null:null;case`VariableDeclaration`:return N(e);default:return null}}const F={FunctionDeclaration:`函数`,MethodDefinition:`方法`,ClassDeclaration:`类`,VariableDeclaration:`变量`,TSInterfaceDeclaration:`接口`,TSTypeAliasDeclaration:`类型别名`,TSEnumDeclaration:`枚举`,PropertyDefinition:`类属性`,TSPropertySignature:`接口属性`,TSEnumMember:`枚举成员`};function I(e){return F[e]||e}function L(e){if(typeof e!=`object`||!e)return!1;let t=e;if(!(`typeParameters`in t)||!t.typeParameters)return!1;let n=t.typeParameters;return typeof n!=`object`||!n?!1:`params`in n&&Array.isArray(n.params)}function _e(e){return L(e)?e.typeParameters.params.map(e=>e.name&&typeof e.name==`object`&&`name`in e.name?String(e.name.name):``).filter(Boolean):[]}function ve(e){return!e.trim().includes(`
|
|
7
|
+
`)}function ye(e){return O(e)?e.key.name:D(e)?e.id.name:`(匿名)`}const be=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求接口属性、类属性、枚举成员使用多行 TSDoc 注释格式`}},createOnce(e){return{TSPropertySignature(t){R(t,e)},PropertyDefinition(t){R(t,e)},TSEnumMember(t){R(t,e)}}}});function R(e,t){let n=E(t.sourceCode.getAllComments(),e);if(!n)return;let r=n.value;if(ve(r)){let n=ye(e);t.report({node:e,message:`"${n}"的注释应使用多行 TSDoc 格式,当前为单行格式`})}}const xe=(0,e.defineRule)({meta:{type:`suggestion`,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=f(n);if(!i)continue;let a=p(i);for(let n of a)g(n)||e.report({node:t,message:`参数 "${n.name}" 缺少描述`})}}}}});function Se(e){if(typeof e!=`object`||!e)return!1;let t=e;return`params`in t&&Array.isArray(t.params)}function Ce(e){return Se(e)?e.params.map(e=>{switch(e.type){case`Identifier`:return e.name??``;case`AssignmentPattern`:return e.left?.name??``;case`RestElement`:return e.argument?.name??``;case`ObjectPattern`:return we(e)??`options`;case`ArrayPattern`:return`args`;case`TSParameterProperty`:return e.parameter?.name??``;default:return``}}).filter(e=>!!e):[]}function we(e){return null}const Te=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求函数参数有 @param 标签`}},createOnce(e){let t=[];function n(n){let r=E(t,n);if(!r)return;let i=Ce(n);if(i.length===0)return;let a=f(r.value);if(!a)return;let o=ne(a),s=i.filter(e=>!o.includes(e));for(let t of s)e.report({node:n,message:`参数 "${t}" 缺少 @param 标签`})}return{Program(){t=e.sourceCode.getAllComments()},FunctionDeclaration(e){n(e)},FunctionExpression(e){n(e)},ArrowFunctionExpression(e){`parent`in e&&e.parent&&e.parent.type===`CallExpression`||n(e)}}}}),Ee=(0,e.defineRule)({meta:{type:`suggestion`,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=f(n);if(!i)continue;let a=m(i);a&&!g(a)&&e.report({node:t,message:`@returns 标签缺少描述`})}}}}});function z(e){return typeof e!=`object`||!e||!(`type`in e)?!1:typeof e.type==`string`}function De(e){return z(e)&&e.type===`ReturnStatement`&&`argument`in e}function Oe(e){return typeof e==`object`&&!!e&&`body`in e}function ke(e){return typeof e==`object`&&!!e&&`returnType`in e}function Ae(e){return z(e)?[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`].includes(e.type):!1}function B(e,t){if(!e||typeof e!=`object`)return!1;let n=e;if(t.has(n))return!1;if(t.add(n),De(n))return!0;if(Ae(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(B(e,t))return!0}else if(`type`in i&&B(i,t))return!0}}return!1}function je(e){if(typeof e!=`object`||!e||!Oe(e)||!e.body)return!1;let t=e.body;return typeof t!=`object`||!t?!1:!(`type`in t)||t.type!==`BlockStatement`?!0:B(t,new WeakSet)}function Me(e){if(typeof e!=`object`||!e||!ke(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(z(t))return t.type===`TSVoidKeyword`}}}return!1}function Ne(e){return je(e)?!Me(e):!1}const Pe=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求有返回值的函数有 @returns 标签`}},createOnce(e){return{FunctionDeclaration(t){V(t,e)},FunctionExpression(t){V(t,e)},ArrowFunctionExpression(t){`parent`in t&&t.parent&&t.parent.type===`CallExpression`||V(t,e)}}}});function V(e,t){if(!Ne(e))return;let n=E(t.sourceCode.getAllComments(),e);if(!n)return;let r=f(n.value);r&&(m(r)||t.report({node:e,message:`缺少 @returns 文档`}))}const Fe=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求 @throws 标签有异常类型`}},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=f(n);if(!i)continue;let a=i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`);for(let n of a)n.type||e.report({node:t,message:`@throws 标签应该包含异常类型,例如:@throws {@link Error} 描述`})}}}}});function H(e){if(typeof e!=`object`||!e)return!1;let t=e;return`body`in t?Array.isArray(t.body):!1}function Ie(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`ThrowStatement`&&`argument`in t}function Le(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`NewExpression`&&`callee`in t}function U(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`Identifier`&&`name`in t}function Re(e){if(typeof e!=`object`||!e)return!1;let t=e;return`consequent`in t&&`alternate`in t}function ze(e){if(typeof e!=`object`||!e)return!1;let t=e;return`block`in t&&`handler`in t}function Be(e){return typeof e!=`object`||!e?!1:`cases`in e}function Ve(e){if(typeof e!=`object`||!e||!(`consequent`in e))return!1;let t=e;return Array.isArray(t.consequent)}function He(e){let t=e.argument;if(Le(t)){let e=t.callee;if(U(e))return e.name}return U(t)?t.name:`Error`}function W(e,t){if(!H(e))return;let n=e;if(Array.isArray(n.body))for(let e of n.body)G(e,t)}function G(e,t){if(!e||typeof e!=`object`)return;let n=e;if(`type`in n&&n.type===`ThrowStatement`&&Ie(n)){let e=He(n);t.push({typeName:e});return}if(`type`in n&&n.type===`IfStatement`&&Re(n)){G(n.consequent,t),n.alternate&&G(n.alternate,t);return}if(`type`in n&&n.type===`TryStatement`&&ze(n)){Ue(n,t);return}if(`type`in n&&n.type===`SwitchStatement`&&Be(n)){We(n,t);return}`type`in n&&n.type===`BlockStatement`&&H(n)&&W(n,t)}function Ue(e,t){H(e.block)&&W(e.block,t),e.handler&&typeof e.handler==`object`&&`body`in e.handler&&e.handler.body&&H(e.handler.body)&&W(e.handler.body,t)}function We(e,t){for(let n of e.cases)if(Ve(n))for(let e of n.consequent)G(e,t)}function Ge(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 W(t,n),n}const Ke=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求抛出异常的函数有 @throws 标签`}},createOnce(e){return{FunctionDeclaration(t){K(t,e)},FunctionExpression(t){K(t,e)},ArrowFunctionExpression(t){K(t,e)}}}});function K(e,t){let n=Ge(e);if(n.length===0)return;let r=E(t.sourceCode.getAllComments(),e);if(!r){q(e,t,n);return}let i=f(r.value);if(!i){q(e,t,n);return}i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`).length===0&&q(e,t,n)}function q(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}} 异常描述`})}const qe={description:`[待填写描述]`,functionDescription:`[待填写函数描述]`,methodDescription:`[待填写方法描述]`,classDescription:`[待填写类描述]`,variableDescription:`[待填写变量描述]`,paramDescription:`[待填写参数描述]`,returnsDescription:`[待填写返回值描述]`,typeParamDescription:`[待填写类型参数描述]`},Je=[/^\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 Ye(e){return Object.values(qe).some(t=>e.includes(t))?!0:Je.some(t=>t.test(e))}function J(e){return typeof e==`object`&&!!e&&`type`in e&&typeof e.type==`string`}function Xe(e){return typeof e==`object`&&!!e&&`parent`in e}function Ze(e){return typeof e==`object`&&!!e&&`init`in e}function Y(e){return typeof e==`object`&&!!e}const Qe=[`FunctionDeclaration`,`MethodDefinition`,`ClassDeclaration`,`VariableDeclaration`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`];function $e(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 et(e,t){if(Xe(e)&&e.parent&&typeof e.parent==`object`&&J(e.parent)&&[`ForStatement`,`ForInStatement`,`ForOfStatement`].includes(e.parent.type))return!0;if(e.type===`VariableDeclaration`){if(t)return!1;if(k(e)&&e.declarations.length>0){let t=e.declarations[0];if(!t)return!0;if(Ze(t)&&t.init&&typeof t.init==`object`&&J(t.init)&&(t.init.type===`ArrowFunctionExpression`||t.init.type===`FunctionExpression`))return!1}return!0}return!!$e(e)}function tt(e){return e.includes(`/**`)}function nt(e,t,n){if(t.skipFile||et(e,t.checkAllVariables))return;let r=E(t.commentsCache,e,n.sourceCode.text);if(!r){let t=I(e.type),r=P(e);n.report({node:e,message:`${t}"${r}"缺少 TSDoc 注释`});return}let i=r.value;if(Ye(i)){let t=I(e.type),r=P(e);n.report({node:e,message:`${t}"${r}"的 TSDoc 注释包含占位描述,请填写实际描述`})}}function rt(e,t){let n=e.getAllComments(),r=e.text;if(r!=null){if(!tt(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 it(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 X=(0,e.defineRule)({meta:{type:`suggestion`,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=rt(e.sourceCode,t);let r=e.options?.[0];t.checkAllVariables=it(r)}};for(let r of Qe)n[r]=n=>nt(n,t,e);return n}});function at(e){return e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`).map(e=>e.name)}const ot=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求泛型有 @typeParam 标签`}},createOnce(e){return{FunctionDeclaration(t){Z(t,e)},FunctionExpression(t){Z(t,e)},ArrowFunctionExpression(t){Z(t,e)},ClassDeclaration(t){Z(t,e)},TSInterfaceDeclaration(t){Z(t,e)},TSTypeAliasDeclaration(t){Z(t,e)}}}});function Z(e,t){if(!L(e))return;let n=_e(e);if(n.length===0)return;let r=E(t.sourceCode.getAllComments(),e);if(!r)return;let i=f(r.value);if(!i)return;let a=at(i),o=n.filter(e=>!a.includes(e));for(let n of o)t.report({node:e,message:`缺少类型参数 "${n}" 的 @typeParam 文档`})}const st=/^(=+)\s+(.+?)\s+(=+)$/;function ct(e){let t=e.trim().match(st);return t?{leadingEquals:t[1]??``,text:t[2]??``,trailingEquals:t[3]??``}:null}const lt=(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求代码块分隔符使用规范格式`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Line`)continue;let n=ct(r.value.trim());if(n&&(n.leadingEquals.length!==20||n.trailingEquals.length!==20)){let r=`=`.repeat(20);e.report({node:t,message:`代码块分隔符格式不正确,应为:// ${r} ${n.text} ${r}`})}}}}}}),ut=/\bTODO(?:\(([^)]+)\))?:?\s*(.*)/i;function dt(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const ft={requireAuthor:!1,requireDescription:!0};function pt(e){return/\bTODO\b/i.test(e)}function mt(e){let t={...ft};if(dt(e)){let n=e;typeof n.requireAuthor==`boolean`&&(t.requireAuthor=n.requireAuthor),typeof n.requireDescription==`boolean`&&(t.requireDescription=n.requireDescription)}return t}function ht(e){let t=e.match(ut);return t?{author:t[1]??``,description:(t[2]??``).trim()}:null}const Q={"no-commented-code":a,"no-description-tag":re,"no-legacy-jsdoc-tags":_,"no-placeholder-description":oe,"param-hyphen-format":ce,"require-blank-line-before-tags":ue,"require-deprecated-alternative":pe,"require-description":ge,"require-multiline-property-comment":be,"require-param":Te,"require-param-description":xe,"require-returns":Pe,"require-returns-description":Ee,"require-throws":Ke,"require-throws-type":Fe,"require-tsdoc":X,"require-type-param":ot,"separator-format":lt,"todo-format":(0,e.defineRule)({meta:{type:`suggestion`,docs:{description:`要求 TODO 注释有描述和作者`}},createOnce(e){let t=mt(e.options?.[0]);return{Program(n){let r=e.sourceCode.getAllComments();for(let i of r){let r=i.value;if(!pt(r))continue;let a=ht(r);a&&(t.requireAuthor&&!a.author&&e.report({node:n,message:`TODO 注释缺少作者信息,格式:TODO(author): 描述`}),t.requireDescription&&!a.description&&e.report({node:n,message:`TODO 注释缺少描述说明`}))}}}}})},$=(0,e.eslintCompatPlugin)({meta:{name:`@longzai-intelligence/tsdoc`},rules:Q});exports.default=$,exports.tsdocPlugin=$,exports.tsdocRules=Q;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as _$_oxlint_plugins0 from "@oxlint/plugins";
|
|
2
|
+
import { Rule } from "@oxlint/plugins";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
declare const tsdocRules: Record<string, Rule>;
|
|
6
|
+
declare const tsdocPlugin: _$_oxlint_plugins0.Plugin;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { tsdocPlugin as default, tsdocPlugin, tsdocRules };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as _$_oxlint_plugins0 from "@oxlint/plugins";
|
|
2
|
+
import { Rule } from "@oxlint/plugins";
|
|
3
|
+
|
|
4
|
+
//#region src/index.d.ts
|
|
5
|
+
declare const tsdocRules: Record<string, Rule>;
|
|
6
|
+
declare const tsdocPlugin: _$_oxlint_plugins0.Plugin;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { tsdocPlugin as default, tsdocPlugin, tsdocRules };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";const n=[/^\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 r(e){let t=e.trim();if(t.length===0)return!1;for(let e of n)if(e.test(t))return!0;return!1}function i(e){let t=e.split(`
|
|
2
|
+
`),n=0,i=0;for(let e of t){let t=e.trim();t.length===0||t===`*`||(i++,r(t.replace(/^\*\s*/,``))&&n++)}return i>0&&n/i>=.5}function a(e){return r(e.trim())}const o=e({meta:{type:`suggestion`,docs:{description:`禁止注释掉的代码`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n)r.type===`Block`?i(r.value)&&e.report({node:t,message:`检测到注释掉的代码,请删除或恢复该代码`}):r.type===`Line`&&a(r.value)&&e.report({node:t,message:`检测到注释掉的代码,请删除或恢复该代码`})}}}}),s=new Map,c=1e3;function l(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 u(e){let t=e.match(/^\{([^}]*)\}\s*(.*)/);return t?{type:t[1]??``,description:t[2]||``}:{description:e,type:``}}function d(e){let t=e.match(/^\{@link\s+([^}]+)\}\s*(.*)/);return t?{type:(t[1]??``).trim(),description:t[2]||``}:{description:e,type:``}}function f(e,t){if(e===`param`||e===`typeParam`||e===`template`){let n=l(t);return{tag:e,name:n.name,description:n.description,type:n.type}}if(e===`returns`||e===`return`){let n=u(t);return{tag:e,name:``,description:n.description,type:n.type}}if(e===`throws`||e===`throw`){let n=d(t);return{tag:e,name:``,description:n.description,type:n.type}}return{tag:e,name:``,description:t,type:``}}function ee(){if(s.size<=c)return;let e=Array.from(s.entries()).sort((e,t)=>e[1].lastAccess-t[1].lastAccess),t=e.slice(0,e.length-c);for(let[e]of t)s.delete(e)}function p(e){let t=s.get(e);if(t)return t.lastAccess=Date.now(),t.result;let n=te(e);return s.set(e,{result:n,lastAccess:Date.now()}),ee(),n}function te(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=f(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 m(e){return e.tags.filter(e=>e.tag===`param`)}function h(e){return e.tags.find(e=>e.tag===`returns`||e.tag===`return`)}function g(e){return e.description.trim().length>0}function _(e){let t=e.description.trim();return!(t.length===0||t===`-`||t===`--`)}function ne(e){return m(e).map(e=>e.name.split(`.`)[0]).filter(e=>typeof e==`string`)}const re=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=p(n);i&&i.tags.some(e=>e.tag===`description`)&&e.report({node:t,message:`请勿使用 description 标签,直接书写描述文本即可`})}}}}}),ie=[`file`,`module`,`author`,`since`];function ae(e){return ie.includes(e)}const oe=e({meta:{type:`suggestion`,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=p(n);if(i)for(let n of i.tags)ae(n.tag)&&e.report({node:t,message:`禁止使用旧版 JSDoc 标签 @${n.tag},该标签在 TSDoc 中已不推荐使用`})}}}}}),se=[`参数描述`,`返回值描述`,`函数描述`,`方法描述`,`类描述`,`变量描述`,`类型参数描述`,`描述`];function v(e){let t=e.trim();t.startsWith(`-`)&&(t=t.slice(1).trim());for(let e of se)if(t===e)return e;return null}function y(e){let t=v(e);return t?`禁止使用占位描述 "${t}",请提供有意义的描述`:null}function b(e){let t=[],n=m(e);for(let e of n){let n=v(e.description);n&&t.push(`@param 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}let r=h(e);if(r){let e=v(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=v(e.description);n&&t.push(`@typeParam 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}return t}const x=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=p(n);if(!i)continue;let a=y(i.description);a&&e.report({node:t,message:a});let o=b(i);for(let n of o)e.report({node:t,message:n})}}}}});function S(e){return e?e.trim().startsWith(`-`):!1}const ce=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=p(n);if(!i)continue;let a=m(i);for(let n of a)S(n.description)||e.report({node:t,message:`参数 "${n.name}" 的描述应该使用 \`-\` 分隔,格式:@param ${n.name} - 描述`})}}}}});function le(e){let t=e.split(`
|
|
6
|
+
`),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 ue=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=p(n);i&&i.tags.length>0&&g(i)&&(le(n)||e.report({node:t,message:`标签前应有一个空行`}))}}}}}),de=[/使用\s+\S+\s+代替/,/请使用\s+\S+/,/use\s+\S+\s+instead/i,/replaced\s+by\s+\S+/i];function fe(e){if(!e)return!1;let t=e.trim();if(t.length===0)return!1;for(let e of de)if(e.test(t))return!0;return t.length>10}const pe=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=p(n);if(!i)continue;let a=i.tags.find(e=>e.tag===`deprecated`);a&&(fe(a.description)||e.report({node:t,message:`@deprecated 标签应该包含替代方案说明,例如:@deprecated 使用 newMethod 代替`}))}}}}});function C(e){if(typeof e!=`object`||!e)return!1;let t=e;return`range`in t&&Array.isArray(t.range)&&t.range.length===2}function w(e){return C(e)}function T(e){return C(e)}function E(e){if(!w(e)||!e.range)return-1;if(!C(e))return e.range[0];if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(T(t)&&t.range)return t.range[0]}if(`parent`in e&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(C(t)&&`type`in t&&typeof t.type==`string`&&[`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type)&&t.range)return t.range[0]}return e.range[0]}function me(e,t,n,r){let i=e.range[1],a=E(t);if(a<0)return!1;let o=n.filter(e=>e.range[0]>=i&&e.range[1]<=a),s=[];if(C(t)&&`decorators`in t){let e=t.decorators;if(Array.isArray(e))for(let t of e)T(t)&&t.range&&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 D(e,t,n){if(!w(t)||!t.range)return null;let r=E(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&&!me(a,t,e,n)?null:a}const he=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`ClassDeclaration`,`VariableDeclaration`,`MethodDefinition`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`],ge=e({meta:{type:`suggestion`,docs:{description:`要求 TSDoc 注释有描述文本`}},createOnce(e){let t=[];function n(n){let r=D(t,n);if(!r)return;let i=p(r.value);i&&(g(i)||e.report({node:n,message:`TSDoc 注释缺少描述`}))}let r={Program(){t=e.sourceCode.getAllComments()}};for(let e of he)r[e]=e=>n(e);return r}});function O(e){if(typeof e!=`object`||!e)return!1;let t=e;if(!(`id`in t))return!1;let n=t.id;return typeof n!=`object`||!n?!1:`name`in n}function k(e){if(typeof e!=`object`||!e)return!1;let t=e;if(!(`key`in t))return!1;let n=t.key;return typeof n!=`object`||!n?!1:`name`in n}function A(e){if(typeof e!=`object`||!e)return!1;let t=e;return`declarations`in t?Array.isArray(t.declarations):!1}function j(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 M(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 N(e){if(!e||typeof e!=`object`)return null;let t=e;return`type`in t&&t.type===`ObjectPattern`&&`properties`in t?j(t.properties):`type`in t&&t.type===`ArrayPattern`&&`elements`in t?M(t.elements):null}function P(e){if(!A(e)||!e.declarations||e.declarations.length===0)return null;let t=e.declarations[0];if(!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 N(n)}return O(t)?t.id?.name??null:null}function F(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 P(e);default:return null}}const I={FunctionDeclaration:`函数`,MethodDefinition:`方法`,ClassDeclaration:`类`,VariableDeclaration:`变量`,TSInterfaceDeclaration:`接口`,TSTypeAliasDeclaration:`类型别名`,TSEnumDeclaration:`枚举`,PropertyDefinition:`类属性`,TSPropertySignature:`接口属性`,TSEnumMember:`枚举成员`};function L(e){return I[e]||e}function R(e){if(typeof e!=`object`||!e)return!1;let t=e;if(!(`typeParameters`in t)||!t.typeParameters)return!1;let n=t.typeParameters;return typeof n!=`object`||!n?!1:`params`in n&&Array.isArray(n.params)}function _e(e){return R(e)?e.typeParameters.params.map(e=>e.name&&typeof e.name==`object`&&`name`in e.name?String(e.name.name):``).filter(Boolean):[]}function ve(e){return!e.trim().includes(`
|
|
7
|
+
`)}function ye(e){return k(e)?e.key.name:O(e)?e.id.name:`(匿名)`}const be=e({meta:{type:`suggestion`,docs:{description:`要求接口属性、类属性、枚举成员使用多行 TSDoc 注释格式`}},createOnce(e){return{TSPropertySignature(t){z(t,e)},PropertyDefinition(t){z(t,e)},TSEnumMember(t){z(t,e)}}}});function z(e,t){let n=D(t.sourceCode.getAllComments(),e);if(!n)return;let r=n.value;if(ve(r)){let n=ye(e);t.report({node:e,message:`"${n}"的注释应使用多行 TSDoc 格式,当前为单行格式`})}}const xe=e({meta:{type:`suggestion`,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=p(n);if(!i)continue;let a=m(i);for(let n of a)_(n)||e.report({node:t,message:`参数 "${n.name}" 缺少描述`})}}}}});function Se(e){if(typeof e!=`object`||!e)return!1;let t=e;return`params`in t&&Array.isArray(t.params)}function Ce(e){return Se(e)?e.params.map(e=>{switch(e.type){case`Identifier`:return e.name??``;case`AssignmentPattern`:return e.left?.name??``;case`RestElement`:return e.argument?.name??``;case`ObjectPattern`:return we(e)??`options`;case`ArrayPattern`:return`args`;case`TSParameterProperty`:return e.parameter?.name??``;default:return``}}).filter(e=>!!e):[]}function we(e){return null}const Te=e({meta:{type:`suggestion`,docs:{description:`要求函数参数有 @param 标签`}},createOnce(e){let t=[];function n(n){let r=D(t,n);if(!r)return;let i=Ce(n);if(i.length===0)return;let a=p(r.value);if(!a)return;let o=ne(a),s=i.filter(e=>!o.includes(e));for(let t of s)e.report({node:n,message:`参数 "${t}" 缺少 @param 标签`})}return{Program(){t=e.sourceCode.getAllComments()},FunctionDeclaration(e){n(e)},FunctionExpression(e){n(e)},ArrowFunctionExpression(e){`parent`in e&&e.parent&&e.parent.type===`CallExpression`||n(e)}}}}),Ee=e({meta:{type:`suggestion`,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=p(n);if(!i)continue;let a=h(i);a&&!_(a)&&e.report({node:t,message:`@returns 标签缺少描述`})}}}}});function B(e){return typeof e!=`object`||!e||!(`type`in e)?!1:typeof e.type==`string`}function De(e){return B(e)&&e.type===`ReturnStatement`&&`argument`in e}function Oe(e){return typeof e==`object`&&!!e&&`body`in e}function ke(e){return typeof e==`object`&&!!e&&`returnType`in e}function Ae(e){return B(e)?[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`].includes(e.type):!1}function V(e,t){if(!e||typeof e!=`object`)return!1;let n=e;if(t.has(n))return!1;if(t.add(n),De(n))return!0;if(Ae(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(V(e,t))return!0}else if(`type`in i&&V(i,t))return!0}}return!1}function je(e){if(typeof e!=`object`||!e||!Oe(e)||!e.body)return!1;let t=e.body;return typeof t!=`object`||!t?!1:!(`type`in t)||t.type!==`BlockStatement`?!0:V(t,new WeakSet)}function Me(e){if(typeof e!=`object`||!e||!ke(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(B(t))return t.type===`TSVoidKeyword`}}}return!1}function Ne(e){return je(e)?!Me(e):!1}const Pe=e({meta:{type:`suggestion`,docs:{description:`要求有返回值的函数有 @returns 标签`}},createOnce(e){return{FunctionDeclaration(t){H(t,e)},FunctionExpression(t){H(t,e)},ArrowFunctionExpression(t){`parent`in t&&t.parent&&t.parent.type===`CallExpression`||H(t,e)}}}});function H(e,t){if(!Ne(e))return;let n=D(t.sourceCode.getAllComments(),e);if(!n)return;let r=p(n.value);r&&(h(r)||t.report({node:e,message:`缺少 @returns 文档`}))}const Fe=e({meta:{type:`suggestion`,docs:{description:`要求 @throws 标签有异常类型`}},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=p(n);if(!i)continue;let a=i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`);for(let n of a)n.type||e.report({node:t,message:`@throws 标签应该包含异常类型,例如:@throws {@link Error} 描述`})}}}}});function U(e){if(typeof e!=`object`||!e)return!1;let t=e;return`body`in t?Array.isArray(t.body):!1}function Ie(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`ThrowStatement`&&`argument`in t}function Le(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`NewExpression`&&`callee`in t}function W(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`Identifier`&&`name`in t}function Re(e){if(typeof e!=`object`||!e)return!1;let t=e;return`consequent`in t&&`alternate`in t}function ze(e){if(typeof e!=`object`||!e)return!1;let t=e;return`block`in t&&`handler`in t}function Be(e){return typeof e!=`object`||!e?!1:`cases`in e}function Ve(e){if(typeof e!=`object`||!e||!(`consequent`in e))return!1;let t=e;return Array.isArray(t.consequent)}function He(e){let t=e.argument;if(Le(t)){let e=t.callee;if(W(e))return e.name}return W(t)?t.name:`Error`}function G(e,t){if(!U(e))return;let n=e;if(Array.isArray(n.body))for(let e of n.body)K(e,t)}function K(e,t){if(!e||typeof e!=`object`)return;let n=e;if(`type`in n&&n.type===`ThrowStatement`&&Ie(n)){let e=He(n);t.push({typeName:e});return}if(`type`in n&&n.type===`IfStatement`&&Re(n)){K(n.consequent,t),n.alternate&&K(n.alternate,t);return}if(`type`in n&&n.type===`TryStatement`&&ze(n)){Ue(n,t);return}if(`type`in n&&n.type===`SwitchStatement`&&Be(n)){We(n,t);return}`type`in n&&n.type===`BlockStatement`&&U(n)&&G(n,t)}function Ue(e,t){U(e.block)&&G(e.block,t),e.handler&&typeof e.handler==`object`&&`body`in e.handler&&e.handler.body&&U(e.handler.body)&&G(e.handler.body,t)}function We(e,t){for(let n of e.cases)if(Ve(n))for(let e of n.consequent)K(e,t)}function Ge(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 G(t,n),n}const Ke=e({meta:{type:`suggestion`,docs:{description:`要求抛出异常的函数有 @throws 标签`}},createOnce(e){return{FunctionDeclaration(t){q(t,e)},FunctionExpression(t){q(t,e)},ArrowFunctionExpression(t){q(t,e)}}}});function q(e,t){let n=Ge(e);if(n.length===0)return;let r=D(t.sourceCode.getAllComments(),e);if(!r){J(e,t,n);return}let i=p(r.value);if(!i){J(e,t,n);return}i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`).length===0&&J(e,t,n)}function J(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}} 异常描述`})}const qe={description:`[待填写描述]`,functionDescription:`[待填写函数描述]`,methodDescription:`[待填写方法描述]`,classDescription:`[待填写类描述]`,variableDescription:`[待填写变量描述]`,paramDescription:`[待填写参数描述]`,returnsDescription:`[待填写返回值描述]`,typeParamDescription:`[待填写类型参数描述]`},Je=[/^\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 Ye(e){return Object.values(qe).some(t=>e.includes(t))?!0:Je.some(t=>t.test(e))}function Y(e){return typeof e==`object`&&!!e&&`type`in e&&typeof e.type==`string`}function Xe(e){return typeof e==`object`&&!!e&&`parent`in e}function Ze(e){return typeof e==`object`&&!!e&&`init`in e}function X(e){return typeof e==`object`&&!!e}const Qe=[`FunctionDeclaration`,`MethodDefinition`,`ClassDeclaration`,`VariableDeclaration`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`];function $e(e){if(!X(e)||e.type!==`TSPropertySignature`)return!1;let t=e.key;return X(t)&&t.type===`Identifier`&&`name`in t&&typeof t.name==`string`?t.name===`null`||t.name===`undefined`:!1}function et(e,t){if(Xe(e)&&e.parent&&typeof e.parent==`object`&&Y(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(Ze(t)&&t.init&&typeof t.init==`object`&&Y(t.init)&&(t.init.type===`ArrowFunctionExpression`||t.init.type===`FunctionExpression`))return!1}return!0}return!!$e(e)}function tt(e){return e.includes(`/**`)}function nt(e,t,n){if(t.skipFile||et(e,t.checkAllVariables))return;let r=D(t.commentsCache,e,n.sourceCode.text);if(!r){let t=L(e.type),r=F(e);n.report({node:e,message:`${t}"${r}"缺少 TSDoc 注释`});return}let i=r.value;if(Ye(i)){let t=L(e.type),r=F(e);n.report({node:e,message:`${t}"${r}"的 TSDoc 注释包含占位描述,请填写实际描述`})}}function rt(e,t){let n=e.getAllComments(),r=e.text;if(r!=null){if(!tt(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 it(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 at=e({meta:{type:`suggestion`,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=rt(e.sourceCode,t);let r=e.options?.[0];t.checkAllVariables=it(r)}};for(let r of Qe)n[r]=n=>nt(n,t,e);return n}});function ot(e){return e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`).map(e=>e.name)}const st=e({meta:{type:`suggestion`,docs:{description:`要求泛型有 @typeParam 标签`}},createOnce(e){return{FunctionDeclaration(t){Z(t,e)},FunctionExpression(t){Z(t,e)},ArrowFunctionExpression(t){Z(t,e)},ClassDeclaration(t){Z(t,e)},TSInterfaceDeclaration(t){Z(t,e)},TSTypeAliasDeclaration(t){Z(t,e)}}}});function Z(e,t){if(!R(e))return;let n=_e(e);if(n.length===0)return;let r=D(t.sourceCode.getAllComments(),e);if(!r)return;let i=p(r.value);if(!i)return;let a=ot(i),o=n.filter(e=>!a.includes(e));for(let n of o)t.report({node:e,message:`缺少类型参数 "${n}" 的 @typeParam 文档`})}const ct=/^(=+)\s+(.+?)\s+(=+)$/;function lt(e){let t=e.trim().match(ct);return t?{leadingEquals:t[1]??``,text:t[2]??``,trailingEquals:t[3]??``}:null}const ut=e({meta:{type:`suggestion`,docs:{description:`要求代码块分隔符使用规范格式`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Line`)continue;let n=lt(r.value.trim());if(n&&(n.leadingEquals.length!==20||n.trailingEquals.length!==20)){let r=`=`.repeat(20);e.report({node:t,message:`代码块分隔符格式不正确,应为:// ${r} ${n.text} ${r}`})}}}}}}),dt=/\bTODO(?:\(([^)]+)\))?:?\s*(.*)/i;function ft(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const pt={requireAuthor:!1,requireDescription:!0};function mt(e){return/\bTODO\b/i.test(e)}function ht(e){let t={...pt};if(ft(e)){let n=e;typeof n.requireAuthor==`boolean`&&(t.requireAuthor=n.requireAuthor),typeof n.requireDescription==`boolean`&&(t.requireDescription=n.requireDescription)}return t}function gt(e){let t=e.match(dt);return t?{author:t[1]??``,description:(t[2]??``).trim()}:null}const Q={"no-commented-code":o,"no-description-tag":re,"no-legacy-jsdoc-tags":oe,"no-placeholder-description":x,"param-hyphen-format":ce,"require-blank-line-before-tags":ue,"require-deprecated-alternative":pe,"require-description":ge,"require-multiline-property-comment":be,"require-param":Te,"require-param-description":xe,"require-returns":Pe,"require-returns-description":Ee,"require-throws":Ke,"require-throws-type":Fe,"require-tsdoc":at,"require-type-param":st,"separator-format":ut,"todo-format":e({meta:{type:`suggestion`,docs:{description:`要求 TODO 注释有描述和作者`}},createOnce(e){let t=ht(e.options?.[0]);return{Program(n){let r=e.sourceCode.getAllComments();for(let i of r){let r=i.value;if(!mt(r))continue;let a=gt(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/tsdoc`},rules:Q});export{$ as default,$ as tsdocPlugin,Q as tsdocRules};
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@longzai-intelligence/oxlint-plugin-tsdoc",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Oxlint TSDoc 插件,提供 TSDoc 注释规范检查规则",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"main": "./dist/index.cjs",
|
|
11
|
+
"module": "./dist/index.mjs",
|
|
12
|
+
"types": "./dist/index.d.mts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": {
|
|
16
|
+
"import": "./dist/index.d.mts",
|
|
17
|
+
"require": "./dist/index.d.cts"
|
|
18
|
+
},
|
|
19
|
+
"import": "./dist/index.mjs",
|
|
20
|
+
"require": "./dist/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./configs/recommended": {
|
|
23
|
+
"types": {
|
|
24
|
+
"import": "./dist/configs/recommended.d.mts",
|
|
25
|
+
"require": "./dist/configs/recommended.d.cts"
|
|
26
|
+
},
|
|
27
|
+
"import": "./dist/configs/recommended.mjs",
|
|
28
|
+
"require": "./dist/configs/recommended.cjs"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"scripts": {
|
|
32
|
+
"build": "tsdown",
|
|
33
|
+
"build:prod": "NODE_ENV=production tsdown",
|
|
34
|
+
"prepublishOnly": "bun run build:prod",
|
|
35
|
+
"dev": "tsdown --watch",
|
|
36
|
+
"clean": "rimraf dist",
|
|
37
|
+
"test": "vitest run",
|
|
38
|
+
"test:watch": "vitest",
|
|
39
|
+
"test:coverage": "vitest run --coverage",
|
|
40
|
+
"lint": "bun run lint:oxlint",
|
|
41
|
+
"lint:oxlint": "oxlint",
|
|
42
|
+
"lint:eslint": "eslint .",
|
|
43
|
+
"lint:fix": "bun run oxc:fix",
|
|
44
|
+
"lint:fix:oxlint": "oxlint --fix",
|
|
45
|
+
"lint:fix:eslint": "eslint . --fix",
|
|
46
|
+
"typecheck": "bun run typecheck:app && bun run typecheck:node",
|
|
47
|
+
"typecheck:app": "tsc --noEmit -p tsconfig/app.json",
|
|
48
|
+
"typecheck:node": "tsc --noEmit -p tsconfig/node.json",
|
|
49
|
+
"lint:file": "bun run lint:file:oxlint",
|
|
50
|
+
"lint:file:oxlint": "oxlint",
|
|
51
|
+
"lint:file:eslint": "eslint",
|
|
52
|
+
"fmt": "oxfmt",
|
|
53
|
+
"fmt:check": "oxfmt --check",
|
|
54
|
+
"oxc": "bun run lint:oxlint && bun run fmt:check",
|
|
55
|
+
"oxc:fix": "bun run lint:fix:oxlint && bun run fmt"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@longzai-intelligence/oxlint-core": "0.0.1",
|
|
59
|
+
"@oxlint/plugins": "^1.64.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@longzai-intelligence/eslint-preset-library": "0.2.13",
|
|
63
|
+
"@longzai-intelligence/oxlint-config": "0.0.1",
|
|
64
|
+
"@longzai-intelligence/oxlint-plugin-architecture": "0.0.1",
|
|
65
|
+
"@longzai-intelligence/oxlint-plugin-code-style": "0.0.1",
|
|
66
|
+
"@longzai-intelligence/oxlint-plugin-package-json": "0.0.1",
|
|
67
|
+
"@longzai-intelligence/oxlint-plugin-perfectionist": "0.0.1",
|
|
68
|
+
"@longzai-intelligence/oxlint-plugin-schema-type-separation": "0.0.1",
|
|
69
|
+
"@longzai-intelligence/oxlint-plugin-stylistic": "0.0.1",
|
|
70
|
+
"@longzai-intelligence/oxlint-plugin-tsdoc": "0.0.1",
|
|
71
|
+
"@longzai-intelligence/oxlint-plugin-typescript-eslint": "0.0.1",
|
|
72
|
+
"@longzai-intelligence/oxlint-plugin-zod": "0.0.1",
|
|
73
|
+
"@longzai-intelligence/oxlint-testing": "0.0.1",
|
|
74
|
+
"@longzai-intelligence/oxlint-utils": "0.0.1",
|
|
75
|
+
"@longzai-intelligence/tsdown-config": "0.0.1",
|
|
76
|
+
"@longzai-intelligence/typescript-config": "0.0.3",
|
|
77
|
+
"@longzai-intelligence/vitest-config": "0.0.10",
|
|
78
|
+
"@types/node": "^25.7.0",
|
|
79
|
+
"acorn": "^8.16.0",
|
|
80
|
+
"oxlint": "^1.64.0",
|
|
81
|
+
"rimraf": "^6.1.3",
|
|
82
|
+
"tsdown": "^0.21.10",
|
|
83
|
+
"typescript": "^6.0.3",
|
|
84
|
+
"vitest": "^4.1.6"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"oxlint": ">=1.0.0"
|
|
88
|
+
}
|
|
89
|
+
}
|