@longzai-intelligence-oxlint/stylistic-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 ADDED
@@ -0,0 +1,17 @@
1
+ # @longzai-intelligence-oxlint/stylistic-plugin
2
+
3
+ ## 意图
4
+
5
+ 在静态检查阶段统一代码排版风格,对标 ESLint 生态 @stylistic 插件,避免格式类问题流入代码评审。
6
+
7
+ ## 定位
8
+
9
+ Oxlint 生态的 stylistic 规则实现插件,通过 `eslintCompatPlugin` 包装以同时兼容 Oxlint 与 ESLint 运行时。
10
+
11
+ ## 职能
12
+
13
+ 提供 `multiline-comment-style` 规则约束多行注释风格、`lines-around-comment` 规则约束注释前后空行、`padding-line-between-statements` 规则约束语句间空行;使用 `defineRule` + `createOnce` 实现以获得最佳性能。
14
+
15
+ ## 实现情况
16
+
17
+ 三条规则均已实现并按规则文件组织,规则集合与插件对象一并导出;当前规则集合聚焦排版维度,处于稳定可用形态。
@@ -0,0 +1,8 @@
1
+ import { OxlintRules } from "@longzai-intelligence-oxlint/core";
2
+ //#region src/configs/recommended.config.d.ts
3
+ /**
4
+ * 推荐规则配置
5
+ */
6
+ declare const recommended: OxlintRules;
7
+ //#endregion
8
+ export { recommended };
@@ -0,0 +1 @@
1
+ const e={"@longzai-intelligence-oxlint/stylistic-plugin/multiline-comment-style":`error`,"@longzai-intelligence-oxlint/stylistic-plugin/lines-around-comment":[`error`,{beforeBlockComment:!0,beforeLineComment:!1,allowBlockStart:!0,allowBlockEnd:!0,allowObjectStart:!0,allowObjectEnd:!0,allowArrayStart:!0,allowArrayEnd:!0,allowClassStart:!0,allowClassEnd:!0,allowInterfaceStart:!0,allowInterfaceEnd:!0,allowTypeStart:!0,allowTypeEnd:!0,allowEnumStart:!0,allowEnumEnd:!0,allowModuleStart:!0,allowModuleEnd:!0}],"@longzai-intelligence-oxlint/stylistic-plugin/padding-line-between-statements":`error`};export{e as recommended};
@@ -0,0 +1,12 @@
1
+ import { Rule } from "@oxlint/plugins";
2
+ //#region src/index.d.ts
3
+ /**
4
+ * stylistic 规则集合
5
+ */
6
+ declare const stylisticRules: Record<string, Rule>;
7
+ /**
8
+ * stylistic 插件
9
+ */
10
+ declare const stylisticPlugin: import("@oxlint/plugins").Plugin;
11
+ //#endregion
12
+ export { stylisticPlugin as default, stylisticPlugin, stylisticRules };
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";function n(){return{isBlockStart:!1,isBlockEnd:!1,isObjectStart:!1,isObjectEnd:!1,isArrayStart:!1,isArrayEnd:!1,isClassStart:!1,isClassEnd:!1,isInterfaceStart:!1,isInterfaceEnd:!1,isTypeStart:!1,isTypeEnd:!1,isEnumStart:!1,isEnumEnd:!1,isModuleStart:!1,isModuleEnd:!1,isFunctionStart:!1,isFunctionEnd:!1}}function r(e){return!!(e.includes(`type `)||e.includes(`extends {`)||e.includes(`type{`)||e.includes(`Array<{`)||e.includes(`Promise<{`)||e.includes(`<{`)||e.includes(`| {`)||e.includes(`as {`)||e.includes(`Record<{`)||e.includes(`Partial<{`)||e.includes(`Required<{`)||e.includes(`Pick<{`)||e.includes(`Omit<{`)||e.includes(`& {`))}function i(e,t){for(let n=2;n<=5&&t>n;n++){let r=e[t-n-1];if(r){let e=r.trimEnd();if(e.includes(`Record<{`)||e.includes(`Partial<{`)||e.includes(`Required<{`)||e.includes(`Pick<{`)||e.includes(`Omit<{`)||e.includes(`Array<{`)||e.includes(`Promise<{`)||e.includes(`type `)||e.includes(`interface `))return!0}}return!1}function a(e){return e.endsWith(`) {`)||e.endsWith(`){`)||/\)\s*(?::\s*[^{]+)?\{/.test(e)||e.includes(`=> {`)}function o(e){return!!(e.endsWith(`) {`)||e.endsWith(`){`)||e===`{`||/: [^{]+ \{$/.test(e)||/\)\s*(?::\s*[^{]+)?\{/.test(e)||e.endsWith(`}> {`)||e===`> {`||e.includes(`try {`)||e.includes(`catch {`)||e.includes(`finally {`)||e.includes(`=> {`)||e.includes(`else {`)||/^\w+\s*\{$/.test(e))}function s(e){let t=e.includes(`namespace `)||e.includes(`namespace{`),n=e.startsWith(`declare global`)||e.startsWith(`declare module`);return e.includes(`module `)||e.includes(`module{`)||t||n}function c(e,t){for(let n=2;n<=10&&t>n;n++){let r=e[t-n-1];if(r){let e=r.trim();if(e.includes(`class `)||e.includes(`class{`))return!0}}return!1}function l(e){let t=/\w\(\{$/.test(e),n=e.endsWith(`, {`),r=/=>\s*\(\{$/.test(e),i=e.includes(`export default {`);return e.includes(`: {`)||e.endsWith(`= {`)||t||n||r||i}function u(e,t,n,u){r(t)?e.isTypeStart=!0:t.trim()===`{`?e[i(n,u)?`isTypeStart`:`isBlockStart`]=!0:t.includes(`interface `)||t.includes(`interface{`)?e.isInterfaceStart=!0:t.includes(`enum `)||t.includes(`enum{`)?e.isEnumStart=!0:s(t)?e.isModuleStart=!0:t.includes(`class `)||t.includes(`class{`)||t===`> {`?e.isClassStart=!0:o(t)?(e.isBlockStart=!0,a(t)&&(e.isFunctionStart=!0)):l(t)?e.isObjectStart=!0:t.includes(`: [`)||t.endsWith(`= [`)||t.endsWith(`[`)?e.isArrayStart=!0:c(n,u)&&(e.isClassStart=!0)}function d(e,t,n){if(t<=1)return;let r=t-2;for(;r>=0;){let e=n[r];if(e&&e.trim().length>0)break;r--}if(r<0)return;let i=n[r];if(!i)return;let a=i.trim();a.endsWith(`{`)||/>+\s*\{\s*$/.test(a)?u(e,a,n,t):a.endsWith(`(`)||a.endsWith(`>`)?e.isBlockStart=!0:a.endsWith(`[`)&&(e.isArrayStart=!0)}function f(e,t,n){if(t>=n.length)return;let r=n[t];if(!r)return;let i=r.trimStart();if(i===`}`){e.isBlockEnd=!0,e.isObjectEnd=!0,e.isClassEnd=!0,e.isInterfaceEnd=!0,e.isTypeEnd=!0,e.isEnumEnd=!0,e.isModuleEnd=!0,e.isFunctionEnd=!0;return}if(i===`};`){e.isBlockEnd=!0,e.isObjectEnd=!0,e.isClassEnd=!0,e.isInterfaceEnd=!0,e.isTypeEnd=!0,e.isEnumEnd=!0,e.isModuleEnd=!0,e.isFunctionEnd=!0;return}if(i.startsWith(`];`)){e.isArrayEnd=!0;return}}function p(e,t){let r=n(),i=e.loc.start.line,a=e.loc.end.line;return d(r,i,t),f(r,a,t),r}const m={beforeBlockComment:!0,afterBlockComment:!1,beforeLineComment:!1,afterLineComment:!1,allowBlockStart:!1,allowBlockEnd:!1,allowObjectStart:!1,allowObjectEnd:!1,allowArrayStart:!1,allowArrayEnd:!1,allowClassStart:!1,allowClassEnd:!1,allowInterfaceStart:!1,allowInterfaceEnd:!1,allowTypeStart:!1,allowTypeEnd:!1,allowEnumStart:!1,allowEnumEnd:!1,allowModuleStart:!1,allowModuleEnd:!1,allowFunctionStart:!1,allowFunctionEnd:!1,ignorePattern:void 0,applyDefaultIgnorePatterns:!0};function h(e,t){if(e.loc.start.line<=1)return!1;let n=_(e.loc.start.line,t);return n?/\w+=\{$/.test(n):!1}function g(e,t){if(e.loc.start.line<=1)return!1;let n=_(e.loc.start.line,t);if(!n||!(n===`}`||/^\w+=("[^"]*"|'[^']*')$/.test(n)||/^\w+=\{.+\}$/.test(n)||/^<[A-Z]\w*$/.test(n)||/^\w+:$/.test(n)))return!1;let r=v(e.loc.end.line,t);return r?/^\w+=/.test(r)||/^\/?>$/.test(r)||r.startsWith(`/>`)||r.startsWith(`(`)||r.startsWith(`<`):!1}function _(e,t){let n=e-2;for(;n>=0;){let e=t[n];if(e&&e.trim().length>0)return e.trim();n--}return null}function v(e,t){let n=e;for(;n<t.length;){let e=t[n];if(e&&e.trim().length>0)return e.trim();n++}return null}function y(e,t){let n=t[e.loc.start.line-1];return n?n.slice(0,e.loc.start.column).trim().length>0:!1}function b(e,t){if(t.length===0)return!1;let n=t[t.length-1];return n?n.loc.end.line+1>=e.loc.start.line:!1}const x=[/^eslint/i,/^jshint/i,/^jslint/i,/^istanbul/i,/^global/i,/^exported/i,/^jscs/i];function S(e,t){let n=e.value.trim();if(t.applyDefaultIgnorePatterns!==!1){for(let e of x)if(e.test(n))return!0}return!!(t.ignorePattern&&new RegExp(t.ignorePattern,`u`).test(n))}function C(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function w(e,t,n){let r=t[n];typeof r==`boolean`&&(e[n]=r)}function T(e,t){w(e,t,`beforeBlockComment`),w(e,t,`afterBlockComment`),w(e,t,`beforeLineComment`),w(e,t,`afterLineComment`),w(e,t,`allowBlockStart`),w(e,t,`allowBlockEnd`),w(e,t,`allowObjectStart`),w(e,t,`allowObjectEnd`),w(e,t,`allowArrayStart`),w(e,t,`allowArrayEnd`),w(e,t,`allowClassStart`),w(e,t,`allowClassEnd`),w(e,t,`allowInterfaceStart`),w(e,t,`allowInterfaceEnd`),w(e,t,`allowTypeStart`),w(e,t,`allowTypeEnd`),w(e,t,`allowEnumStart`),w(e,t,`allowEnumEnd`),w(e,t,`allowModuleStart`),w(e,t,`allowModuleEnd`),w(e,t,`allowFunctionStart`),w(e,t,`allowFunctionEnd`),w(e,t,`applyDefaultIgnorePatterns`)}function E(e,t,n){let r=t[n];typeof r==`string`&&(e[n]=r)}function D(e){let t={...m};return C(e)?(T(t,e),E(t,e,`ignorePattern`),t):t}function O(e,t){return e<=1||t[e-2]?.trim()===``}function k(e,t){return e>=t.length||t[e]?.trim()===``}function A(e,t){return e.isBlockStart&&(t.allowBlockStart??!1)||e.isObjectStart&&(t.allowObjectStart??!1)||e.isArrayStart&&(t.allowArrayStart??!1)||e.isClassStart&&(t.allowClassStart??!1)||e.isInterfaceStart&&(t.allowInterfaceStart??!1)||e.isTypeStart&&(t.allowTypeStart??!1)||e.isEnumStart&&(t.allowEnumStart??!1)||e.isModuleStart&&(t.allowModuleStart??!1)||e.isFunctionStart&&(t.allowFunctionStart??!1)}function j(e,t){return e.isBlockEnd&&(t.allowBlockEnd??!1)||e.isObjectEnd&&(t.allowObjectEnd??!1)||e.isArrayEnd&&(t.allowArrayEnd??!1)||e.isClassEnd&&(t.allowClassEnd??!1)||e.isInterfaceEnd&&(t.allowInterfaceEnd??!1)||e.isTypeEnd&&(t.allowTypeEnd??!1)||e.isEnumEnd&&(t.allowEnumEnd??!1)||e.isModuleEnd&&(t.allowModuleEnd??!1)||e.isFunctionEnd&&(t.allowFunctionEnd??!1)}function M(e,t,n,r,i){let a=e.type===`Block`;if(a&&n.beforeBlockComment||!a&&n.beforeLineComment){if(A(i,n))return;let o=e.loc.start.line;O(o,t)||r.report({loc:{start:e.loc.start,end:e.loc.start},message:a?`块注释前需要空行`:`行注释前需要空行`,fix:n=>{let r=0;for(let n=0;n<e.loc.start.line-1;n++)r+=(t[n]?.length??0)+1;return n.insertTextBeforeRange([r,r],`
2
+ `)}})}}function N(e,t,n,r,i){let a=e.type===`Block`;if(a&&n.afterBlockComment||!a&&n.afterLineComment){if(j(i,n))return;let o=e.loc.end.line;k(o,t)||r.report({loc:{start:e.loc.end,end:e.loc.end},message:a?`块注释后需要空行`:`行注释后需要空行`,fix:t=>t.insertTextAfterRange([e.range[1],e.range[1]],`
3
+ `)})}}function P(e,t,n,r,i=[],a=!1,o=!1){if(y(e,t)||S(e,n))return;let s=b(e,i),c=p(e,t),l=h(e,t)||g(e,t);!a&&!s&&!l&&M(e,t,n,r,c),o||N(e,t,n,r,c)}const F=e({meta:{type:`layout`,fixable:`whitespace`,docs:{description:`要求在注释前后有空行`},schema:[{type:`object`,properties:{beforeBlockComment:{type:`boolean`},afterBlockComment:{type:`boolean`},beforeLineComment:{type:`boolean`},afterLineComment:{type:`boolean`},allowBlockStart:{type:`boolean`},allowBlockEnd:{type:`boolean`},allowObjectStart:{type:`boolean`},allowObjectEnd:{type:`boolean`},allowArrayStart:{type:`boolean`},allowArrayEnd:{type:`boolean`},allowClassStart:{type:`boolean`},allowClassEnd:{type:`boolean`},allowInterfaceStart:{type:`boolean`},allowInterfaceEnd:{type:`boolean`},allowTypeStart:{type:`boolean`},allowTypeEnd:{type:`boolean`},allowEnumStart:{type:`boolean`},allowEnumEnd:{type:`boolean`},allowModuleStart:{type:`boolean`},allowModuleEnd:{type:`boolean`},allowFunctionStart:{type:`boolean`},allowFunctionEnd:{type:`boolean`},ignorePattern:{type:`string`},applyDefaultIgnorePatterns:{type:`boolean`}},additionalProperties:!1}]},createOnce(e){let t=[],n=[];return{Program(){let r=D(e.options?.[0]);t=e.sourceCode.text.split(`
4
+ `),n=[];let i=e.sourceCode.getAllComments();for(let a=0;a<i.length;a++){let o=i[a];if(!o)continue;let s=i[a+1],c=s!==void 0&&s.loc.start.line<=o.loc.end.line+1;P(o,t,r,e,n,!1,c),n.push(o)}}}}}),I=e({meta:{type:`layout`,docs:{description:`强制多行注释使用星号块样式`}},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=n.split(`
5
+ `);if(!(r.length<=1))for(let n=1;n<r.length-1;n++){let i=r[n]?.trim();if(i&&!i.startsWith(`*`)){e.report({loc:{start:t.loc.start,end:t.loc.end},message:`多行注释的中间行应以 "*" 开头`});break}}}}}}});function L(e){return e.type===`ExportNamedDeclaration`||e.type===`ExportDefaultDeclaration`||e.type===`ExportAllDeclaration`}function R(e,t,n){if(n-t<=1)return!1;for(let r=t+1;r<n;r++)if(e[r-1]?.trim()===``)return!0;return!1}function z(e){return e.type===`Program`}function B(e,t,n){for(let r=1;r<e.length;r++){let i=e[r-1],a=e[r];if(!(i===void 0||a===void 0)&&L(i)&&L(a)){let e=i.loc.end.line,r=a.loc.start.line;R(t,e,r)||n.report({loc:a.loc.start,message:`export 语句之间需要空行`})}}}const V={"multiline-comment-style":I,"lines-around-comment":F,"padding-line-between-statements":e({meta:{type:`layout`,docs:{description:`要求在 export 语句之间有空行`}},createOnce(e){return{Program(t){let n=e.sourceCode.text.split(`
6
+ `),r=z(t)?t:null;r&&B(r.body,n,e)}}}})},H=t({meta:{name:`@longzai-intelligence-oxlint/stylistic-plugin`},rules:V});export{H as default,H as stylisticPlugin,V as stylisticRules};
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@longzai-intelligence-oxlint/stylistic-plugin",
3
+ "version": "0.1.0",
4
+ "description": "Oxlint stylistic 兼容插件,提供 @stylistic 规则的 Oxlint 实现",
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
+ },
43
+ "devDependencies": {
44
+ "@vitest/coverage-v8": "^4.1.10",
45
+ "typescript": "^6.0.3"
46
+ },
47
+ "peerDependencies": {
48
+ "oxlint": ">=1.0.0"
49
+ }
50
+ }