@master/eslint-plugin-css 2.0.0-beta.186 → 2.0.0-beta.188
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/config.d.ts +8 -0
- package/dist/config.js +1 -0
- package/dist/config.mjs +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/plugin.d.ts +3 -0
- package/dist/plugin.js +1 -0
- package/dist/plugin.mjs +1 -0
- package/dist/rules/class-collision.d.ts +3 -0
- package/dist/rules/class-collision.js +1 -0
- package/dist/rules/class-collision.mjs +1 -0
- package/dist/rules/class-order.d.ts +3 -0
- package/dist/rules/class-order.js +1 -0
- package/dist/rules/class-order.mjs +1 -0
- package/dist/rules/class-validation.d.ts +3 -0
- package/dist/rules/class-validation.js +1 -0
- package/dist/rules/class-validation.mjs +1 -0
- package/dist/settings.d.ts +7 -0
- package/dist/settings.js +1 -0
- package/dist/settings.mjs +1 -0
- package/dist/utils/are-declarations-equal.d.ts +1 -0
- package/dist/utils/are-declarations-equal.js +1 -0
- package/dist/utils/are-declarations-equal.mjs +1 -0
- package/dist/utils/ast.d.ts +31 -0
- package/dist/utils/ast.js +1 -0
- package/dist/utils/ast.mjs +1 -0
- package/dist/utils/define-visitors.d.ts +5 -0
- package/dist/utils/define-visitors.js +1 -0
- package/dist/utils/define-visitors.mjs +1 -0
- package/dist/utils/resolve-context.d.ts +5 -0
- package/dist/utils/resolve-context.js +1 -0
- package/dist/utils/resolve-context.mjs +1 -0
- package/package.json +1 -1
- package/lib/index.js +0 -5
- package/lib/rules/class-order.js +0 -202
- package/lib/rules/class-validation.js +0 -123
- package/lib/utils/ast.js +0 -218
- package/lib/utils/resolve-context.js +0 -21
- package/tests/frameworks/react.js +0 -55
- package/tests/frameworks/svelte.js +0 -24
- package/tests/frameworks/vue.js +0 -24
- package/tests/order.js +0 -66
- package/tests/validation.js +0 -69
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var o=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var t=Object.getOwnPropertyNames;var n=Object.prototype.hasOwnProperty;var i=(a,s)=>{for(var c in s)o(a,c,{get:s[c],enumerable:!0})},d=(a,s,c,e)=>{if(s&&typeof s=="object"||typeof s=="function")for(let r of t(s))!n.call(a,r)&&r!==c&&o(a,r,{get:()=>s[r],enumerable:!(e=l(s,r))||e.enumerable});return a};var m=a=>d(o({},"__esModule",{value:!0}),a);var w={};i(w,{default:()=>u});module.exports=m(w);const f={rules:{"@master/css/class-order":"warn","@master/css/class-validation":"error","@master/css/class-collision":"warn"}};var u=f;
|
package/dist/config.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const s={rules:{"@master/css/class-order":"warn","@master/css/class-validation":"error","@master/css/class-collision":"warn"}};var a=s;export{a as default};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var g=Object.create;var p=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var l=Object.getOwnPropertyNames;var a=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty;var d=(s,m,o,n)=>{if(m&&typeof m=="object"||typeof m=="function")for(let r of l(m))!u.call(s,r)&&r!==o&&p(s,r,{get:()=>m[r],enumerable:!(n=c(m,r))||n.enumerable});return s};var i=(s,m,o)=>(o=s!=null?g(a(s)):{},d(m||!s||!s.__esModule?p(o,"default",{value:s,enumerable:!0}):o,s));var t=i(require("./plugin")),e=i(require("./config")),f=i(require("./settings"));module.exports={...t.default,configs:{recommended:{plugins:["@master/css"],...e.default},flat:{plugins:{"@master/css":t.default},...e.default}},settings:f.default};
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var t=(i,s)=>()=>(s||i((s={exports:{}}).exports,s),s.exports);import m from"./plugin";import o from"./config";import e from"./settings";var n=t((l,r)=>{r.exports={...m,configs:{recommended:{plugins:["@master/css"],...o},flat:{plugins:{"@master/css":m},...o}},settings:e}});export default n();
|
package/dist/plugin.d.ts
ADDED
package/dist/plugin.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.create;var t=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var u=Object.getPrototypeOf,g=Object.prototype.hasOwnProperty;var E=(s,i)=>{for(var l in i)t(s,l,{get:i[l],enumerable:!0})},n=(s,i,l,a)=>{if(i&&typeof i=="object"||typeof i=="function")for(let o of f(i))!g.call(s,o)&&o!==l&&t(s,o,{get:()=>i[o],enumerable:!(a=d(i,o))||a.enumerable});return s};var r=(s,i,l)=>(l=s!=null?p(u(s)):{},n(i||!s||!s.__esModule?t(l,"default",{value:s,enumerable:!0}):l,s)),L=s=>n(t({},"__esModule",{value:!0}),s);var x={};E(x,{default:()=>v});module.exports=L(x);var e=r(require("./rules/class-collision")),m=r(require("./rules/class-order")),c=r(require("./rules/class-validation"));const S={meta:{name:"@master/eslint-plugin-css"},rules:{"class-collision":e.default,"class-order":m.default,"class-validation":c.default}};var v=S;
|
package/dist/plugin.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import s from"./rules/class-collision";import i from"./rules/class-order";import l from"./rules/class-validation";const o={meta:{name:"@master/eslint-plugin-css"},rules:{"class-collision":s,"class-order":i,"class-validation":l}};var n=o;export{n as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var I=Object.create;var f=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var V=Object.getOwnPropertyNames;var q=Object.getPrototypeOf,A=Object.prototype.hasOwnProperty;var D=(e,s)=>{for(var o in s)f(e,o,{get:s[o],enumerable:!0})},R=(e,s,o,r)=>{if(s&&typeof s=="object"||typeof s=="function")for(let l of V(s))!A.call(e,l)&&l!==o&&f(e,l,{get:()=>s[l],enumerable:!(r=M(s,l))||r.enumerable});return e};var m=(e,s,o)=>(o=e!=null?I(q(e)):{},R(s||!e||!e.__esModule?f(o,"default",{value:e,enumerable:!0}):o,e)),K=e=>R(f({},"__esModule",{value:!0}),e);var U={};D(U,{default:()=>O});module.exports=K(U);var S=m(require("../utils/ast")),$=m(require("../utils/are-declarations-equal")),v=m(require("../utils/define-visitors")),x=m(require("../utils/resolve-context")),y=require("@master/css-validator"),O={meta:{docs:{description:"Avoid applying classes with the same CSS declaration",category:"Stylistic Issues",recommended:!1,url:"https://beta.css.master.co/docs/code-linting#class-collision-detection"},messages:{collisionClass:"{{message}}"},fixable:"code"},create(e){const{options:s,settings:o,config:r}=(0,x.default)(e);return(0,v.default)({context:e,options:s,settings:o,config:r},(E,L=null)=>{S.parseNodeRecursive(E,L,(c,C,N,T,b)=>{const j=e.sourceCode.lines,k=C.loc.start.line,w=C.loc.end.line,p={};c.forEach(i=>{p[i]=(0,y.createValidRules)(i,{config:r})[0]});for(let i=0;i<c.length;i++){const u=c[i],g=p[u],d=[];if(g)for(let n=0;n<c.length;n++){const a=c[n],t=p[a];i!==n&&t&&(0,$.default)(g.declarations,t.declarations)&&g.stateToken===t.stateToken&&d.push(a)}if(d.length>0){const n=d.map(t=>`"${t}"`).join(" and ");let a=N;for(const t of d){const h=t.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g,"\\$1");a=a.replace(new RegExp(`\\s+${h}|${h}\\s+`),"")}e.report({loc:S.findLoc(u,j,k,w),messageId:"collisionClass",data:{message:`"${u}" applies the same CSS declarations as ${n}.`},fix:function(t){return t.replaceTextRange([T,b],a)}})}}},!1,!1,o.ignoredKeys,e)})}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as u from"../utils/ast";import E from"../utils/are-declarations-equal";import L from"../utils/define-visitors";import N from"../utils/resolve-context";import{createValidRules as T}from"@master/css-validator";var A={meta:{docs:{description:"Avoid applying classes with the same CSS declaration",category:"Stylistic Issues",recommended:!1,url:"https://beta.css.master.co/docs/code-linting#class-collision-detection"},messages:{collisionClass:"{{message}}"},fixable:"code"},create(i){const{options:g,settings:d,config:f}=N(i);return L({context:i,options:g,settings:d,config:f},(C,h=null)=>{u.parseNodeRecursive(C,h,(l,m,R,S,$)=>{const v=i.sourceCode.lines,x=m.loc.start.line,y=m.loc.end.line,a={};l.forEach(s=>{a[s]=T(s,{config:f})[0]});for(let s=0;s<l.length;s++){const r=l[s],c=a[r],n=[];if(c)for(let o=0;o<l.length;o++){const t=l[o],e=a[t];s!==o&&e&&E(c.declarations,e.declarations)&&c.stateToken===e.stateToken&&n.push(t)}if(n.length>0){const o=n.map(e=>`"${e}"`).join(" and ");let t=R;for(const e of n){const p=e.replace(/(\\|\.|\(|\)|\[|\]|\{|\}|\+|\*|\?|\^|\$|\||\/)/g,"\\$1");t=t.replace(new RegExp(`\\s+${p}|${p}\\s+`),"")}i.report({loc:u.findLoc(r,v,x,y),messageId:"collisionClass",data:{message:`"${r}" applies the same CSS declarations as ${o}.`},fix:function(e){return e.replaceTextRange([S,$],t)}})}}},!1,!1,d.ignoredKeys,i)})}};export{A as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var $=Object.create;var y=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var I=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var q=(e,a)=>{for(var n in a)y(e,n,{get:a[n],enumerable:!0})},T=(e,a,n,C)=>{if(a&&typeof a=="object"||typeof a=="function")for(let r of I(a))!P.call(e,r)&&r!==n&&y(e,r,{get:()=>a[r],enumerable:!(C=F(a,r))||C.enumerable});return e};var N=(e,a,n)=>(n=e!=null?$(O(e)):{},T(a||!e||!e.__esModule?y(n,"default",{value:e,enumerable:!0}):n,e)),A=e=>T(y({},"__esModule",{value:!0}),e);var U={};q(U,{default:()=>B});module.exports=A(U);var m=N(require("../utils/ast")),V=N(require("../utils/define-visitors")),R=N(require("../utils/resolve-context")),S=require("@master/css"),B={meta:{docs:{description:"Enforce a consistent and logical order of classes",category:"Stylistic Issues",recommended:!1,url:"https://beta.css.master.co/docs/code-linting#consistent-class-order"},messages:{invalidClassOrder:"No consistent class order followed."},fixable:"code"},create:function(e){const{options:a,settings:n,config:C}=(0,R.default)(e),r=(l,s=null)=>{let i=null,p=null,d=null,E="",v="";if(s===null){i=m.extractValueFromNode(l);const t=m.extractRangeFromNode(l);l.type==="TextAttribute"?(p=t[0],d=t[1]):(p=t[0]+1,d=t[1]-1)}else switch(s.type){case"Identifier":return;case"TemplateLiteral":s.expressions.forEach(o=>{r(l,o)}),s.quasis.forEach(o=>{r(l,o)});return;case"ConditionalExpression":r(l,s.consequent),r(l,s.alternate);return;case"LogicalExpression":r(l,s.right);return;case"ArrayExpression":s.elements.forEach(o=>{r(l,o)});return;case"ObjectExpression":const t=l.callee&&l.callee.name==="classnames",x=l.key&&l.key.type==="VDirectiveKey";s.properties.forEach(o=>{const b=t||x?o.key:o.value;r(l,b)});return;case"Property":r(l,s.key);break;case"Literal":i=s.value,p=s.range[0]+1,d=s.range[1]-1;break;case"SvelteLiteral":if(i=s.value,i==="")return;p=s.range[0],d=s.range[1];break;case"TemplateElement":if(i=s.value.raw,i==="")return;p=s.range[0],d=s.range[1];const c=e.sourceCode.getText(s);E=m.getTemplateElementPrefix(c,i),v=m.getTemplateElementSuffix(c,i),i=m.getTemplateElementBody(c,E,v);break}const{classNames:h,whitespaces:g,headSpace:k,tailSpace:L}=m.extractClassnamesFromValue(i);if(h.length<=1)return;let f=(0,S.reorderForReadableClasses)(h,C).filter(t=>h.includes(t));f=h.filter(t=>!f.includes(t)).concat(f).filter(t=>t.trim()!=="");let u="";for(let t=0;t<f.length;t++){const x=g[t]??"",c=f[t];u+=k?`${x}${c}`:`${c}${x}`,c&&(!L&&t===f.length-1&&(u=u.replace(/\s+$/,"")),k&&L&&t===f.length-1&&(u+=g[g.length-1]??""))}if(i!==u){u=E+u+v;const x=e.sourceCode.lines,c=l.loc.start.line,o=l.loc.end.line,b={loc:m.findLoc(i,x,c,o),messageId:"invalidClassOrder",fix:function(w){return w.replaceTextRange([p,d],u)}};e.report(b)}};return(0,V.default)({context:e,options:a,settings:n,config:C},r)}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as c from"../utils/ast";import L from"../utils/define-visitors";import T from"../utils/resolve-context";import{reorderForReadableClasses as V}from"@master/css";var I={meta:{docs:{description:"Enforce a consistent and logical order of classes",category:"Stylistic Issues",recommended:!1,url:"https://beta.css.master.co/docs/code-linting#consistent-class-order"},messages:{invalidClassOrder:"No consistent class order followed."},fixable:"code"},create:function(p){const{options:b,settings:N,config:E}=T(p),a=(t,e=null)=>{let l=null,u=null,f=null,x="",C="";if(e===null){l=c.extractValueFromNode(t);const s=c.extractRangeFromNode(t);t.type==="TextAttribute"?(u=s[0],f=s[1]):(u=s[0]+1,f=s[1]-1)}else switch(e.type){case"Identifier":return;case"TemplateLiteral":e.expressions.forEach(r=>{a(t,r)}),e.quasis.forEach(r=>{a(t,r)});return;case"ConditionalExpression":a(t,e.consequent),a(t,e.alternate);return;case"LogicalExpression":a(t,e.right);return;case"ArrayExpression":e.elements.forEach(r=>{a(t,r)});return;case"ObjectExpression":const s=t.callee&&t.callee.name==="classnames",m=t.key&&t.key.type==="VDirectiveKey";e.properties.forEach(r=>{const y=s||m?r.key:r.value;a(t,y)});return;case"Property":a(t,e.key);break;case"Literal":l=e.value,u=e.range[0]+1,f=e.range[1]-1;break;case"SvelteLiteral":if(l=e.value,l==="")return;u=e.range[0],f=e.range[1];break;case"TemplateElement":if(l=e.value.raw,l==="")return;u=e.range[0],f=e.range[1];const i=p.sourceCode.getText(e);x=c.getTemplateElementPrefix(i,l),C=c.getTemplateElementSuffix(i,l),l=c.getTemplateElementBody(i,x,C);break}const{classNames:d,whitespaces:h,headSpace:v,tailSpace:g}=c.extractClassnamesFromValue(l);if(d.length<=1)return;let o=V(d,E).filter(s=>d.includes(s));o=d.filter(s=>!o.includes(s)).concat(o).filter(s=>s.trim()!=="");let n="";for(let s=0;s<o.length;s++){const m=h[s]??"",i=o[s];n+=v?`${m}${i}`:`${i}${m}`,i&&(!g&&s===o.length-1&&(n=n.replace(/\s+$/,"")),v&&g&&s===o.length-1&&(n+=h[h.length-1]??""))}if(l!==n){n=x+n+C;const m=p.sourceCode.lines,i=t.loc.start.line,r=t.loc.end.line,y={loc:c.findLoc(l,m,i,r),messageId:"invalidClassOrder",fix:function(k){return k.replaceTextRange([u,f],n)}};p.report(y)}};return L({context:p,options:b,settings:N,config:E},a)}};export{I as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var N=Object.create;var n=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var U=Object.getPrototypeOf,I=Object.prototype.hasOwnProperty;var b=(s,e)=>{for(var o in e)n(s,o,{get:e[o],enumerable:!0})},g=(s,e,o,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of S(e))!I.call(s,r)&&r!==o&&n(s,r,{get:()=>e[r],enumerable:!(a=R(e,r))||a.enumerable});return s};var l=(s,e,o)=>(o=s!=null?N(U(s)):{},g(e||!s||!s.__esModule?n(o,"default",{value:s,enumerable:!0}):o,s)),M=s=>g(n({},"__esModule",{value:!0}),s);var E={};b(E,{default:()=>D});module.exports=M(E);var t=l(require("../utils/ast")),p=l(require("../utils/define-visitors")),C=l(require("../utils/resolve-context")),w=require("@master/css-validator"),D={meta:{docs:{description:"Detect syntax errors early when writing classes",category:"Stylistic Issues",recommended:!1,url:"https://beta.css.master.co/docs/code-linting#syntax-error-checks"},messages:{invalidClass:"{{message}}",disallowUnknownClass:"{{message}}"},fixable:null},create:function(s){const{options:e,settings:o,config:a}=(0,C.default)(s);return(0,p.default)({context:s,options:e,settings:o,config:a},(v,y=null)=>{t.parseNodeRecursive(v,y,(k,c)=>{const d=s.sourceCode.lines,m=c.loc.start.line,f=c.loc.end.line;for(const i of k){const{isMasterCSS:L,errors:u}=(0,w.validate)(i,{config:a});if(u.length>0)for(const h of u)L?s.report({loc:t.findLoc(i,d,m,f),messageId:"invalidClass",data:{message:h.message+"."}}):e.disallowUnknownClass&&s.report({loc:t.findLoc(i,d,m,f),messageId:"disallowUnknownClass",data:{message:`"${i}" is not a valid or known class.`}})}},!1,!1,o.ignoredKeys,s)})}};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import*as o from"../utils/ast";import C from"../utils/define-visitors";import w from"../utils/resolve-context";import{validate as v}from"@master/css-validator";var U={meta:{docs:{description:"Detect syntax errors early when writing classes",category:"Stylistic Issues",recommended:!1,url:"https://beta.css.master.co/docs/code-linting#syntax-error-checks"},messages:{invalidClass:"{{message}}",disallowUnknownClass:"{{message}}"},fixable:null},create:function(s){const{options:r,settings:a,config:i}=w(s);return C({context:s,options:r,settings:a,config:i},(m,f=null)=>{o.parseNodeRecursive(m,f,(u,n)=>{const l=s.sourceCode.lines,t=n.loc.start.line,c=n.loc.end.line;for(const e of u){const{isMasterCSS:g,errors:d}=v(e,{config:i});if(d.length>0)for(const p of d)g?s.report({loc:o.findLoc(e,l,t,c),messageId:"invalidClass",data:{message:p.message+"."}}):r.disallowUnknownClass&&s.report({loc:o.findLoc(e,l,t,c),messageId:"disallowUnknownClass",data:{message:`"${e}" is not a valid or known class.`}})}},!1,!1,a.ignoredKeys,s)})}};export{U as default};
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.defineProperty;var n=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var o=Object.prototype.hasOwnProperty;var r=(a,s)=>{for(var t in s)e(a,t,{get:s[t],enumerable:!0})},d=(a,s,t,l)=>{if(s&&typeof s=="object"||typeof s=="function")for(let c of i(s))!o.call(a,c)&&c!==t&&e(a,c,{get:()=>s[c],enumerable:!(l=n(s,c))||l.enumerable});return a};var g=a=>d(e({},"__esModule",{value:!0}),a);var u={};r(u,{default:()=>f});module.exports=g(u);const m={calleeMatching:"^(classnames|clsx|ctl|cva|cv|classVariant|styled(?:\\.\\w+)?)",classMatching:"^class(Name)?$",ignoredKeys:["compoundVariants","defaultVariants"],config:"master.css.*"};var f=m;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const s={calleeMatching:"^(classnames|clsx|ctl|cva|cv|classVariant|styled(?:\\.\\w+)?)",classMatching:"^class(Name)?$",ignoredKeys:["compoundVariants","defaultVariants"],config:"master.css.*"};var a=s;export{a as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function areDeclarationsEqual(aDeclarations: any, bDeclarations: any): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var s=Object.defineProperty;var c=Object.getOwnPropertyDescriptor;var f=Object.getOwnPropertyNames;var l=Object.prototype.hasOwnProperty;var u=(t,e)=>{for(var r in e)s(t,r,{get:e[r],enumerable:!0})},y=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of f(e))!l.call(t,n)&&n!==r&&s(t,n,{get:()=>e[n],enumerable:!(o=c(e,n))||o.enumerable});return t};var p=t=>y(s({},"__esModule",{value:!0}),t);var O={};u(O,{default:()=>a});module.exports=p(O);function a(t,e){const r=Object.keys(t),o=Object.keys(e);if(r.length!==o.length)return!1;for(const n of r)if(!Object.prototype.hasOwnProperty.call(e,n))return!1;return!0}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function s(r,e){const t=Object.keys(r),n=Object.keys(e);if(t.length!==n.length)return!1;for(const o of t)if(!Object.prototype.hasOwnProperty.call(e,o))return!1;return!0}export{s as default};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Rule } from 'eslint';
|
|
2
|
+
export declare function extractRangeFromNode(node: any): any;
|
|
3
|
+
export declare function extractValueFromNode(node: any): any;
|
|
4
|
+
export declare function extractClassnamesFromValue(classStr: any): {
|
|
5
|
+
classNames: string[];
|
|
6
|
+
whitespaces: string[];
|
|
7
|
+
headSpace: boolean;
|
|
8
|
+
tailSpace: boolean;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Inspect and parse an abstract syntax node and run a callback function
|
|
12
|
+
*
|
|
13
|
+
* @param {ASTNode} rootNode The current root node being parsed by eslint
|
|
14
|
+
* @param {ASTNode} childNode The AST node child argument being checked
|
|
15
|
+
* @param {Function} cb The callback function
|
|
16
|
+
* @param {Boolean} skipConditional Optional, indicate distinct parsing for conditional nodes
|
|
17
|
+
* @param {Boolean} isolate Optional, set internally to isolate parsing and validation on conditional children
|
|
18
|
+
* @param {Array} ignoredKeys Optional, set object keys which should not be parsed e.g. for `cva`
|
|
19
|
+
* @returns {void}
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseNodeRecursive(rootNode: any, childNode: any, cb: any, skipConditional?: boolean, isolate?: boolean, ignoredKeys?: any[], context?: Rule.RuleContext): void;
|
|
22
|
+
export declare function getTemplateElementPrefix(text: any, raw: any): any;
|
|
23
|
+
export declare function getTemplateElementSuffix(text: any, raw: any): any;
|
|
24
|
+
export declare function getTemplateElementBody(text: any, prefix: any, suffix: any): any;
|
|
25
|
+
export declare function findLoc(text: any, lines: any, startLine: any, endLine: any): {
|
|
26
|
+
start: any;
|
|
27
|
+
end: {
|
|
28
|
+
line: any;
|
|
29
|
+
column: any;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var E=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var V=Object.prototype.hasOwnProperty;var F=(e,t)=>{for(var r in t)E(e,r,{get:t[r],enumerable:!0})},P=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let u of j(t))!V.call(e,u)&&u!==r&&E(e,u,{get:()=>t[u],enumerable:!(s=O(t,u))||s.enumerable});return e};var q=e=>P(E({},"__esModule",{value:!0}),e);var J={};F(J,{extractClassnamesFromValue:()=>y,extractRangeFromNode:()=>L,extractValueFromNode:()=>w,findLoc:()=>I,getTemplateElementBody:()=>B,getTemplateElementPrefix:()=>h,getTemplateElementSuffix:()=>R,parseNodeRecursive:()=>x});module.exports=q(J);const S=/([\t\n\f\r ]+)/;function L(e){if(e.type==="TextAttribute"&&e.name==="class")return[e.valueSpan.fullStart.offset,e.valueSpan.end.offset];switch(e.value.type){case"JSXExpressionContainer":return e.value.expression.range;default:return e.value.range}}function w(e){if(e.type==="TextAttribute"&&e.name==="class")return e.value;switch(e.value.type){case"JSXExpressionContainer":return e.value.expression.value;case"VExpressionContainer":switch(e.value.expression.type){case"ArrayExpression":return e.value.expression.elements;case"ObjectExpression":return e.value.expression.properties}return e.value.expression.value;default:return e.value.value}}function y(e){if(typeof e!="string")return{classNames:[],whitespaces:[],headSpace:!1,tailSpace:!1};const t=e.split(S);t[0]===""&&t.shift(),t[t.length-1]===""&&t.pop();const r=S.test(t[0]),s=S.test(t[t.length-1]),u=(a,f)=>r?f%2!==0:f%2===0,n=(a,f)=>r?f%2===0:f%2!==0,m=t.filter(u),l=t.filter(n);return{classNames:m,whitespaces:l,headSpace:r,tailSpace:s}}function x(e,t,r,s=!1,u=!1,n=[],m=null){let l,a,f=null,i=null,g="",v="";if(t===null){if(l=w(e),{classNames:a}=y(l),a=[...new Set(a)],a.length===0)return;const c=L(e);e.type==="TextAttribute"?(f=c[0],i=c[1]):(f=c[0]+1,i=c[1]-1),r(a,e,l,f,i,g,v)}else{if(t===void 0)return;{const c=s?!0:u;let A=!1;switch(t.type){case"TemplateLiteral":t.expressions.forEach(p=>{x(e,p,r,s,c,n)}),t.quasis.forEach(p=>{x(e,p,r,s,u,n)});return;case"ConditionalExpression":x(e,t.consequent,r,s,c,n),x(e,t.alternate,r,s,c,n);return;case"LogicalExpression":x(e,t.right,r,s,c,n);return;case"ArrayExpression":t.elements.forEach(p=>{x(e,p,r,s,c,n)});return;case"ObjectExpression":t.properties.forEach(p=>{const C=e.callee&&e.callee.name==="classnames";p.type!=="SpreadElement"&&(p.key.type==="Identifier"&&n.includes(p.key.name)||x(e,C?p.key:p.value,r,s,c,n))});return;case"Property":x(e,t.key,r,s,c,n);return;case"Literal":A=!0,l=t.value,f=t.range[0]+1,i=t.range[1]-1;break;case"SvelteLiteral":l=t.value,f=t.range[0],i=t.range[1];break;case"TemplateElement":l=t.value.raw,f=t.range[0],i=t.range[1];const T=m?.sourceCode.getText(t)??"";g=h(T,l),v=R(T,l);break}if({classNames:a}=y(l),a=[...new Set(a)],a.length===0)return;r(a,u?null:e,l,f,i,g,v)}}}function h(e,t){return e.indexOf(t)===0?"":e.split(t).shift()}function R(e,t){return e.indexOf(t)===-1?"":e.split(t).pop()}function B(e,t,r){let s=e.split(t);return s.shift(),s=s.join(t).split(r),s.pop(),s.join(r)}function I(e,t,r,s){const u=e.match(/.+(?:\r\n|\n)?/g);let n=0,m=null,l=!1;for(let a=r;a<=s;a++){const i=t[a-1].indexOf(u[n].replace(/\r\n|\n/,""));if(i!==-1){if(n===0&&(m={line:a,column:i}),n===u.length-1)return{start:m,end:{line:a,column:i+e.length}};l=!0,n++}else l&&(l=!1,n=0,m=null)}return null}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E=/([\t\n\f\r ]+)/;function w(e){if(e.type==="TextAttribute"&&e.name==="class")return[e.valueSpan.fullStart.offset,e.valueSpan.end.offset];switch(e.value.type){case"JSXExpressionContainer":return e.value.expression.range;default:return e.value.range}}function h(e){if(e.type==="TextAttribute"&&e.name==="class")return e.value;switch(e.value.type){case"JSXExpressionContainer":return e.value.expression.value;case"VExpressionContainer":switch(e.value.expression.type){case"ArrayExpression":return e.value.expression.elements;case"ObjectExpression":return e.value.expression.properties}return e.value.expression.value;default:return e.value.value}}function y(e){if(typeof e!="string")return{classNames:[],whitespaces:[],headSpace:!1,tailSpace:!1};const t=e.split(E);t[0]===""&&t.shift(),t[t.length-1]===""&&t.pop();const r=E.test(t[0]),s=E.test(t[t.length-1]),p=(a,u)=>r?u%2!==0:u%2===0,n=(a,u)=>r?u%2===0:u%2!==0,m=t.filter(p),l=t.filter(n);return{classNames:m,whitespaces:l,headSpace:r,tailSpace:s}}function x(e,t,r,s=!1,p=!1,n=[],m=null){let l,a,u=null,c=null,g="",v="";if(t===null){if(l=h(e),{classNames:a}=y(l),a=[...new Set(a)],a.length===0)return;const f=w(e);e.type==="TextAttribute"?(u=f[0],c=f[1]):(u=f[0]+1,c=f[1]-1),r(a,e,l,u,c,g,v)}else{if(t===void 0)return;{const f=s?!0:p;let T=!1;switch(t.type){case"TemplateLiteral":t.expressions.forEach(i=>{x(e,i,r,s,f,n)}),t.quasis.forEach(i=>{x(e,i,r,s,p,n)});return;case"ConditionalExpression":x(e,t.consequent,r,s,f,n),x(e,t.alternate,r,s,f,n);return;case"LogicalExpression":x(e,t.right,r,s,f,n);return;case"ArrayExpression":t.elements.forEach(i=>{x(e,i,r,s,f,n)});return;case"ObjectExpression":t.properties.forEach(i=>{const L=e.callee&&e.callee.name==="classnames";i.type!=="SpreadElement"&&(i.key.type==="Identifier"&&n.includes(i.key.name)||x(e,L?i.key:i.value,r,s,f,n))});return;case"Property":x(e,t.key,r,s,f,n);return;case"Literal":T=!0,l=t.value,u=t.range[0]+1,c=t.range[1]-1;break;case"SvelteLiteral":l=t.value,u=t.range[0],c=t.range[1];break;case"TemplateElement":l=t.value.raw,u=t.range[0],c=t.range[1];const S=m?.sourceCode.getText(t)??"";g=R(S,l),v=A(S,l);break}if({classNames:a}=y(l),a=[...new Set(a)],a.length===0)return;r(a,p?null:e,l,u,c,g,v)}}}function R(e,t){return e.indexOf(t)===0?"":e.split(t).shift()}function A(e,t){return e.indexOf(t)===-1?"":e.split(t).pop()}function V(e,t,r){let s=e.split(t);return s.shift(),s=s.join(t).split(r),s.pop(),s.join(r)}function F(e,t,r,s){const p=e.match(/.+(?:\r\n|\n)?/g);let n=0,m=null,l=!1;for(let a=r;a<=s;a++){const c=t[a-1].indexOf(p[n].replace(/\r\n|\n/,""));if(c!==-1){if(n===0&&(m={line:a,column:c}),n===p.length-1)return{start:m,end:{line:a,column:c+e.length}};l=!0,n++}else l&&(l=!1,n=0,m=null)}return null}export{y as extractClassnamesFromValue,w as extractRangeFromNode,h as extractValueFromNode,F as findLoc,V as getTemplateElementBody,R as getTemplateElementPrefix,A as getTemplateElementSuffix,x as parseNodeRecursive};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=Object.defineProperty;var m=Object.getOwnPropertyDescriptor;var o=Object.getOwnPropertyNames;var x=Object.prototype.hasOwnProperty;var E=(s,r)=>{for(var t in r)p(s,t,{get:r[t],enumerable:!0})},v=(s,r,t,l)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of o(r))!x.call(s,i)&&i!==t&&p(s,i,{get:()=>r[i],enumerable:!(l=m(r,i))||l.enumerable});return s};var g=s=>v(p({},"__esModule",{value:!0}),s);var V={};E(V,{default:()=>f});module.exports=g(V);function f({context:s,settings:r},t){const l=e=>{let a="";const n=e.callee||e.tag;return n.type==="Identifier"&&(a=n.name),n.type==="MemberExpression"&&(a=`${n.object.name}.${n.property.name}`),new RegExp(r.calleeMatching).test(a)},i=function(e){l(e)&&e.arguments.forEach(a=>{t(e,a)})},u=new RegExp(r.classMatching),c={CallExpression:i,JSXAttribute:function(e){!e.name||!u.test(e.name.name)||(e.value&&e.value.type==="Literal"?t(e):e.value&&e.value.type==="JSXExpressionContainer"&&t(e,e.value.expression))},SvelteAttribute:function(e){if(!(!e.key?.name||!u.test(e.key.name)))for(const a of e.value)t(e,a)},TextAttribute:function(e){!e.name||!u.test(e.name)||t(e)},TaggedTemplateExpression:function(e){if(l(e)){t(e,e.quasi);return}}},y={CallExpression:i,VAttribute:function(e){e.value&&e.value.type==="VLiteral"?t(e):e.value&&e.value.type==="VExpressionContainer"&&e.value.expression.type==="ArrayExpression"?e.value.expression.elements.forEach(a=>{t(e,a)}):e.value&&e.value.type==="VExpressionContainer"&&e.value.expression.type==="ObjectExpression"&&e.value.expression.properties.forEach(a=>{t(e,a)})}};return s.sourceCode.parserServices==null||s.sourceCode.parserServices.defineTemplateBodyVisitor==null?c:s.sourceCode.parserServices.defineTemplateBodyVisitor(y,c)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function f({context:a,settings:l},r){const n=e=>{let t="";const s=e.callee||e.tag;return s.type==="Identifier"&&(t=s.name),s.type==="MemberExpression"&&(t=`${s.object.name}.${s.property.name}`),new RegExp(l.calleeMatching).test(t)},u=function(e){n(e)&&e.arguments.forEach(t=>{r(e,t)})},i=new RegExp(l.classMatching),p={CallExpression:u,JSXAttribute:function(e){!e.name||!i.test(e.name.name)||(e.value&&e.value.type==="Literal"?r(e):e.value&&e.value.type==="JSXExpressionContainer"&&r(e,e.value.expression))},SvelteAttribute:function(e){if(!(!e.key?.name||!i.test(e.key.name)))for(const t of e.value)r(e,t)},TextAttribute:function(e){!e.name||!i.test(e.name)||r(e)},TaggedTemplateExpression:function(e){if(n(e)){r(e,e.quasi);return}}},c={CallExpression:u,VAttribute:function(e){e.value&&e.value.type==="VLiteral"?r(e):e.value&&e.value.type==="VExpressionContainer"&&e.value.expression.type==="ArrayExpression"?e.value.expression.elements.forEach(t=>{r(e,t)}):e.value&&e.value.type==="VExpressionContainer"&&e.value.expression.type==="ObjectExpression"&&e.value.expression.properties.forEach(t=>{r(e,t)})}};return a.sourceCode.parserServices==null||a.sourceCode.parserServices.defineTemplateBodyVisitor==null?p:a.sourceCode.parserServices.defineTemplateBodyVisitor(c,p)}export{f as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var m=Object.create;var n=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var u=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var d=(o,t)=>{for(var s in t)n(o,s,{get:t[s],enumerable:!0})},r=(o,t,s,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let e of a(t))!b.call(o,e)&&e!==s&&n(o,e,{get:()=>t[e],enumerable:!(i=l(t,e))||i.enumerable});return o};var f=(o,t,s)=>(s=o!=null?m(u(o)):{},r(t||!o||!o.__esModule?n(s,"default",{value:o,enumerable:!0}):s,o)),j=o=>r(n({},"__esModule",{value:!0}),o);var v={};d(v,{default:()=>p});module.exports=j(v);var g=f(require("../settings")),c=f(require("explore-config"));function p(o){const t=Object.assign(g.default,o.settings?.["@master/css"]),s=t?.config;return{settings:t,options:o.options[0]||{},config:typeof s=="object"?s:(0,c.default)(t?.config||"")}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import e from"../settings";import n from"explore-config";function i(t){const o=Object.assign(e,t.settings?.["@master/css"]),s=o?.config;return{settings:o,options:t.options[0]||{},config:typeof s=="object"?s:n(o?.config||"")}}export{i as default};
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@master/eslint-plugin-css","scripts":{"
|
|
1
|
+
{"name":"@master/eslint-plugin-css","scripts":{"build":"techor pack 'src/**/*.ts'","dev":"pnpm run build --watch --no-declare","test":"jest","type-check":"tsc --noEmit","lint":"eslint src"},"keywords":["mastercss","eslint","eslintplugin"],"license":"MIT","description":"Master CSS ESLint Plugin","author":"Aoyue Design LLC.","funding":"https://css.master.co/docs/donate","homepage":"https://css.master.co","bugs":{"url":"https://github.com/master-co/css/issues"},"repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/eslint-plugin"},"sideEffects":false,"main":"./dist/index.js","types":"./dist/index.d.ts","exports":"./dist/index.js","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","files":["dist"],"publishConfig":{"access":"public"},"dependencies":{"@master/css":"^2.0.0-beta.188","@master/css-validator":"^2.0.0-beta.188","explore-config":"^2.2.10"},"devDependencies":{"@angular-eslint/template-parser":"^16.2.0","@types/node":"^20.6.0","@typescript-eslint/parser":"^5.50.0","@typescript-eslint/utils":"^6.9.0","eslint":"^8.0.0","svelte-eslint-parser":"^0.33.1","vue-eslint-parser":"^9.3.1"},"version":"2.0.0-beta.188"}
|
package/lib/index.js
DELETED
package/lib/rules/class-order.js
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const astUtil = require('../utils/ast')
|
|
4
|
-
const resolveContext = require('../utils/resolve-context')
|
|
5
|
-
const { reorderForReadableClasses } = require('@master/css')
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
meta: {
|
|
9
|
-
docs: {
|
|
10
|
-
description: 'Enforce a consistent and logical order of classes',
|
|
11
|
-
category: 'Stylistic Issues',
|
|
12
|
-
recommended: false,
|
|
13
|
-
url: 'https://beta.css.master.co/docs/code-linting#enforce-a-consistent-and-logical-order-of-classes',
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
invalidClassOrder: 'No consistent class order followed.',
|
|
17
|
-
},
|
|
18
|
-
fixable: 'code'
|
|
19
|
-
},
|
|
20
|
-
create: function (context) {
|
|
21
|
-
const { options, settings, config } = resolveContext(context)
|
|
22
|
-
const sortNodeArgumentValue = (node, arg = null) => {
|
|
23
|
-
let originalClassNamesValue = null
|
|
24
|
-
let start = null
|
|
25
|
-
let end = null
|
|
26
|
-
let prefix = ''
|
|
27
|
-
let suffix = ''
|
|
28
|
-
if (arg === null) {
|
|
29
|
-
originalClassNamesValue = astUtil.extractValueFromNode(node)
|
|
30
|
-
const range = astUtil.extractRangeFromNode(node)
|
|
31
|
-
if (node.type === 'TextAttribute') {
|
|
32
|
-
start = range[0]
|
|
33
|
-
end = range[1]
|
|
34
|
-
} else {
|
|
35
|
-
start = range[0] + 1
|
|
36
|
-
end = range[1] - 1
|
|
37
|
-
}
|
|
38
|
-
} else {
|
|
39
|
-
switch (arg.type) {
|
|
40
|
-
case 'Identifier':
|
|
41
|
-
return
|
|
42
|
-
case 'TemplateLiteral':
|
|
43
|
-
arg.expressions.forEach((exp) => {
|
|
44
|
-
sortNodeArgumentValue(node, exp)
|
|
45
|
-
})
|
|
46
|
-
arg.quasis.forEach((quasis) => {
|
|
47
|
-
sortNodeArgumentValue(node, quasis)
|
|
48
|
-
})
|
|
49
|
-
return
|
|
50
|
-
case 'ConditionalExpression':
|
|
51
|
-
sortNodeArgumentValue(node, arg.consequent)
|
|
52
|
-
sortNodeArgumentValue(node, arg.alternate)
|
|
53
|
-
return
|
|
54
|
-
case 'LogicalExpression':
|
|
55
|
-
sortNodeArgumentValue(node, arg.right)
|
|
56
|
-
return
|
|
57
|
-
case 'ArrayExpression':
|
|
58
|
-
arg.elements.forEach((el) => {
|
|
59
|
-
sortNodeArgumentValue(node, el)
|
|
60
|
-
})
|
|
61
|
-
return
|
|
62
|
-
case 'ObjectExpression':
|
|
63
|
-
const isUsedByClassNamesPlugin = node.callee && node.callee.name === 'classnames'
|
|
64
|
-
const isVue = node.key && node.key.type === 'VDirectiveKey'
|
|
65
|
-
arg.properties.forEach((prop) => {
|
|
66
|
-
const propVal = isUsedByClassNamesPlugin || isVue ? prop.key : prop.value
|
|
67
|
-
sortNodeArgumentValue(node, propVal)
|
|
68
|
-
})
|
|
69
|
-
return
|
|
70
|
-
case 'Property':
|
|
71
|
-
sortNodeArgumentValue(node, arg.key)
|
|
72
|
-
break
|
|
73
|
-
case 'Literal':
|
|
74
|
-
originalClassNamesValue = arg.value
|
|
75
|
-
start = arg.range[0] + 1
|
|
76
|
-
end = arg.range[1] - 1
|
|
77
|
-
break
|
|
78
|
-
case 'SvelteLiteral':
|
|
79
|
-
originalClassNamesValue = arg.value
|
|
80
|
-
if (originalClassNamesValue === '') {
|
|
81
|
-
return
|
|
82
|
-
}
|
|
83
|
-
start = arg.range[0]
|
|
84
|
-
end = arg.range[1]
|
|
85
|
-
break
|
|
86
|
-
case 'TemplateElement':
|
|
87
|
-
originalClassNamesValue = arg.value.raw
|
|
88
|
-
if (originalClassNamesValue === '') {
|
|
89
|
-
return
|
|
90
|
-
}
|
|
91
|
-
start = arg.range[0]
|
|
92
|
-
end = arg.range[1]
|
|
93
|
-
// https://github.com/eslint/eslint/issues/13360
|
|
94
|
-
// The problem is that range computation includes the backticks (`test`)
|
|
95
|
-
// but value.raw does not include them, so there is a mismatch.
|
|
96
|
-
// start/end does not include the backticks, therefore it matches value.raw.
|
|
97
|
-
const txt = context.getSourceCode().getText(arg)
|
|
98
|
-
prefix = astUtil.getTemplateElementPrefix(txt, originalClassNamesValue)
|
|
99
|
-
suffix = astUtil.getTemplateElementSuffix(txt, originalClassNamesValue)
|
|
100
|
-
originalClassNamesValue = astUtil.getTemplateElementBody(txt, prefix, suffix)
|
|
101
|
-
break
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
let { classNames, whitespaces, headSpace, tailSpace } =
|
|
106
|
-
astUtil.extractClassnamesFromValue(originalClassNamesValue)
|
|
107
|
-
|
|
108
|
-
if (classNames.length <= 1) {
|
|
109
|
-
// Don't run sorting for a single or empty className
|
|
110
|
-
return
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
let orderedClassNames = reorderForReadableClasses(classNames, config)
|
|
114
|
-
.filter(eachOrderedClassName => classNames.includes(eachOrderedClassName))
|
|
115
|
-
|
|
116
|
-
orderedClassNames = classNames.filter(x => !orderedClassNames.includes(x))
|
|
117
|
-
.concat(orderedClassNames)
|
|
118
|
-
.filter(x => x.trim() !== '')
|
|
119
|
-
|
|
120
|
-
// Generates the validated/sorted attribute value
|
|
121
|
-
let validatedClassNamesValue = ''
|
|
122
|
-
for (let i = 0; i < orderedClassNames.length; i++) {
|
|
123
|
-
const w = whitespaces[i] ?? ''
|
|
124
|
-
const cls = orderedClassNames[i]
|
|
125
|
-
validatedClassNamesValue += headSpace ? `${w}${cls}` : `${cls}${w}`
|
|
126
|
-
if (headSpace && tailSpace && i === orderedClassNames.length - 1) {
|
|
127
|
-
validatedClassNamesValue += whitespaces[whitespaces.length - 1] ?? ''
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (originalClassNamesValue !== validatedClassNamesValue) {
|
|
132
|
-
validatedClassNamesValue = prefix + validatedClassNamesValue + suffix
|
|
133
|
-
context.report({
|
|
134
|
-
node: node,
|
|
135
|
-
messageId: 'invalidClassOrder',
|
|
136
|
-
fix: function (fixer) {
|
|
137
|
-
return fixer.replaceTextRange([start, end], validatedClassNamesValue)
|
|
138
|
-
},
|
|
139
|
-
})
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const callExpressionVisitor = function (node) {
|
|
144
|
-
const calleeStr = astUtil.calleeToString(node.callee)
|
|
145
|
-
if (settings.callees.findIndex((name) => calleeStr === name) === -1) {
|
|
146
|
-
return
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
node.arguments.forEach((arg) => {
|
|
150
|
-
sortNodeArgumentValue(node, arg)
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const scriptVisitor = {
|
|
155
|
-
CallExpression: callExpressionVisitor,
|
|
156
|
-
JSXAttribute: function (node) {
|
|
157
|
-
if (!node.name || !new RegExp(settings.classMatching).test(node.name.name)) return
|
|
158
|
-
if (node.value && node.value.type === 'Literal') {
|
|
159
|
-
sortNodeArgumentValue(node)
|
|
160
|
-
} else if (node.value && node.value.type === 'JSXExpressionContainer') {
|
|
161
|
-
sortNodeArgumentValue(node, node.value.expression)
|
|
162
|
-
}
|
|
163
|
-
},
|
|
164
|
-
SvelteAttribute: function (node) {
|
|
165
|
-
if (!node.key?.name || !new RegExp(settings.classMatching).test(node.key.name)) return
|
|
166
|
-
for (const eachValue of node.value) {
|
|
167
|
-
sortNodeArgumentValue(node, eachValue)
|
|
168
|
-
}
|
|
169
|
-
},
|
|
170
|
-
TextAttribute: function (node) {
|
|
171
|
-
if (!node.name || !new RegExp(settings.classMatching).test(node.name)) return
|
|
172
|
-
sortNodeArgumentValue(node)
|
|
173
|
-
},
|
|
174
|
-
TaggedTemplateExpression: function (node) {
|
|
175
|
-
if (!settings.tags.includes(node.tag.name)) {
|
|
176
|
-
return
|
|
177
|
-
}
|
|
178
|
-
sortNodeArgumentValue(node, node.quasi)
|
|
179
|
-
},
|
|
180
|
-
}
|
|
181
|
-
const templateBodyVisitor = {
|
|
182
|
-
CallExpression: callExpressionVisitor,
|
|
183
|
-
VAttribute: function (node) {
|
|
184
|
-
if (node.value && node.value.type === 'VLiteral') {
|
|
185
|
-
sortNodeArgumentValue(node)
|
|
186
|
-
} else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ArrayExpression') {
|
|
187
|
-
node.value.expression.elements.forEach((arg) => {
|
|
188
|
-
sortNodeArgumentValue(node, arg)
|
|
189
|
-
})
|
|
190
|
-
} else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ObjectExpression') {
|
|
191
|
-
sortNodeArgumentValue(node, prop)
|
|
192
|
-
}
|
|
193
|
-
},
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (context.parserServices == null || context.parserServices.defineTemplateBodyVisitor == null) {
|
|
197
|
-
return scriptVisitor
|
|
198
|
-
} else {
|
|
199
|
-
return context.parserServices.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor)
|
|
200
|
-
}
|
|
201
|
-
},
|
|
202
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const astUtil = require('../utils/ast')
|
|
4
|
-
const resolveContext = require('../utils/resolve-context')
|
|
5
|
-
const { validate } = require('@master/css-validator')
|
|
6
|
-
|
|
7
|
-
module.exports = {
|
|
8
|
-
meta: {
|
|
9
|
-
docs: {
|
|
10
|
-
description: 'Check the validity of classes with your configuration',
|
|
11
|
-
category: 'Stylistic Issues',
|
|
12
|
-
recommended: false,
|
|
13
|
-
url: 'https://beta.css.master.co/docs/code-linting#check-the-validity-of-classes-with-your-configuration',
|
|
14
|
-
},
|
|
15
|
-
messages: {
|
|
16
|
-
invalidClass: '{{message}}',
|
|
17
|
-
disallowTraditionalClass: '{{message}}',
|
|
18
|
-
},
|
|
19
|
-
fixable: null
|
|
20
|
-
},
|
|
21
|
-
create: function (context) {
|
|
22
|
-
const { options, settings, config } = resolveContext(context)
|
|
23
|
-
const checkNodeArgumentValue = (node, arg = null) => {
|
|
24
|
-
astUtil.parseNodeRecursive(
|
|
25
|
-
node,
|
|
26
|
-
arg,
|
|
27
|
-
(classNames, node) => {
|
|
28
|
-
const sourceCode = context.getSourceCode()
|
|
29
|
-
const sourceCodeLines = sourceCode.lines
|
|
30
|
-
const nodeStartLine = node.loc.start.line
|
|
31
|
-
const nodeEndLine = node.loc.end.line
|
|
32
|
-
for (const className of classNames) {
|
|
33
|
-
const { isMasterCSS, errors } = validate(className, { config })
|
|
34
|
-
if (errors.length > 0) {
|
|
35
|
-
for (const error of errors) {
|
|
36
|
-
if (isMasterCSS) {
|
|
37
|
-
context.report({
|
|
38
|
-
loc: astUtil.findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine),
|
|
39
|
-
messageId: 'invalidClass',
|
|
40
|
-
data: {
|
|
41
|
-
message: error.message + '.',
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
} else if (!isMasterCSS && options.disallowTraditionalClass) {
|
|
45
|
-
context.report({
|
|
46
|
-
loc: astUtil.findLoc(className, sourceCodeLines, nodeStartLine, nodeEndLine),
|
|
47
|
-
messageId: 'disallowTraditionalClass',
|
|
48
|
-
data: {
|
|
49
|
-
message: `Disallow a traditional class \`${className}\`.`,
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
false,
|
|
58
|
-
false,
|
|
59
|
-
settings.ignoredKeys
|
|
60
|
-
)
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const callExpressionVisitor = function (node) {
|
|
64
|
-
const calleeStr = astUtil.calleeToString(node.callee)
|
|
65
|
-
if (settings.callees.findIndex((name) => calleeStr === name) === -1) {
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
node.arguments.forEach((arg) => {
|
|
70
|
-
checkNodeArgumentValue(node, arg)
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const scriptVisitor = {
|
|
75
|
-
CallExpression: callExpressionVisitor,
|
|
76
|
-
JSXAttribute: function (node) {
|
|
77
|
-
if (!node.name || !new RegExp(settings.classMatching).test(node.name.name)) return
|
|
78
|
-
if (node.value && node.value.type === 'Literal') {
|
|
79
|
-
checkNodeArgumentValue(node)
|
|
80
|
-
} else if (node.value && node.value.type === 'JSXExpressionContainer') {
|
|
81
|
-
checkNodeArgumentValue(node, node.value.expression)
|
|
82
|
-
}
|
|
83
|
-
},
|
|
84
|
-
SvelteAttribute: function (node) {
|
|
85
|
-
if (!node.key?.name || !new RegExp(settings.classMatching).test(node.key.name)) return
|
|
86
|
-
for (const eachValue of node.value) {
|
|
87
|
-
checkNodeArgumentValue(node, eachValue)
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
|
-
TextAttribute: function (node) {
|
|
91
|
-
if (!node.name || !new RegExp(settings.classMatching).test(node.name)) return
|
|
92
|
-
checkNodeArgumentValue(node)
|
|
93
|
-
},
|
|
94
|
-
TaggedTemplateExpression: function (node) {
|
|
95
|
-
if (!settings.tags.includes(node.tag.name)) {
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
checkNodeArgumentValue(node, node.quasi)
|
|
99
|
-
},
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const templateBodyVisitor = {
|
|
103
|
-
CallExpression: callExpressionVisitor,
|
|
104
|
-
VAttribute: function (node) {
|
|
105
|
-
if (node.value && node.value.type === 'VLiteral') {
|
|
106
|
-
checkNodeArgumentValue(node)
|
|
107
|
-
} else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ArrayExpression') {
|
|
108
|
-
node.value.expression.elements.forEach((arg) => {
|
|
109
|
-
checkNodeArgumentValue(node, arg)
|
|
110
|
-
})
|
|
111
|
-
} else if (node.value && node.value.type === 'VExpressionContainer' && node.value.expression.type === 'ObjectExpression') {
|
|
112
|
-
checkNodeArgumentValue(node, prop)
|
|
113
|
-
}
|
|
114
|
-
},
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (context.parserServices == null || context.parserServices.defineTemplateBodyVisitor == null) {
|
|
118
|
-
return scriptVisitor
|
|
119
|
-
} else {
|
|
120
|
-
return context.parserServices.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor)
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
}
|
package/lib/utils/ast.js
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const separatorRegEx = /([\t\n\f\r ]+)/
|
|
4
|
-
|
|
5
|
-
function calleeToString(calleeNode) {
|
|
6
|
-
if (calleeNode.type === 'Identifier') {
|
|
7
|
-
return calleeNode.name
|
|
8
|
-
}
|
|
9
|
-
if (calleeNode.type === 'MemberExpression') {
|
|
10
|
-
return `${calleeNode.object.name}.${calleeNode.property.name}`
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function extractRangeFromNode(node) {
|
|
15
|
-
if (node.type === 'TextAttribute' && node.name === 'class') {
|
|
16
|
-
return [node.valueSpan.fullStart.offset, node.valueSpan.end.offset]
|
|
17
|
-
}
|
|
18
|
-
switch (node.value.type) {
|
|
19
|
-
case 'JSXExpressionContainer':
|
|
20
|
-
return node.value.expression.range
|
|
21
|
-
default:
|
|
22
|
-
return node.value.range
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function extractValueFromNode(node) {
|
|
27
|
-
if (node.type === 'TextAttribute' && node.name === 'class') {
|
|
28
|
-
return node.value
|
|
29
|
-
}
|
|
30
|
-
switch (node.value.type) {
|
|
31
|
-
case 'JSXExpressionContainer':
|
|
32
|
-
return node.value.expression.value
|
|
33
|
-
case 'VExpressionContainer':
|
|
34
|
-
switch (node.value.expression.type) {
|
|
35
|
-
case 'ArrayExpression':
|
|
36
|
-
return node.value.expression.elements
|
|
37
|
-
case 'ObjectExpression':
|
|
38
|
-
return node.value.expression.properties
|
|
39
|
-
}
|
|
40
|
-
return node.value.expression.value
|
|
41
|
-
default:
|
|
42
|
-
return node.value.value
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function extractClassnamesFromValue(classStr) {
|
|
47
|
-
if (typeof classStr !== 'string') {
|
|
48
|
-
return { classNames: [], whitespaces: [], headSpace: false, tailSpace: false }
|
|
49
|
-
}
|
|
50
|
-
let parts = classStr.split(separatorRegEx)
|
|
51
|
-
if (parts[0] === '') {
|
|
52
|
-
parts.shift()
|
|
53
|
-
}
|
|
54
|
-
if (parts[parts.length - 1] === '') {
|
|
55
|
-
parts.pop()
|
|
56
|
-
}
|
|
57
|
-
let headSpace = separatorRegEx.test(parts[0])
|
|
58
|
-
let tailSpace = separatorRegEx.test(parts[parts.length - 1])
|
|
59
|
-
const isClass = (_, i) => (headSpace ? i % 2 !== 0 : i % 2 === 0)
|
|
60
|
-
const isNotClass = (_, i) => (headSpace ? i % 2 === 0 : i % 2 !== 0)
|
|
61
|
-
let classNames = parts.filter(isClass)
|
|
62
|
-
let whitespaces = parts.filter(isNotClass)
|
|
63
|
-
return { classNames: classNames, whitespaces: whitespaces, headSpace: headSpace, tailSpace: tailSpace }
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Inspect and parse an abstract syntax node and run a callback function
|
|
69
|
-
*
|
|
70
|
-
* @param {ASTNode} rootNode The current root node being parsed by eslint
|
|
71
|
-
* @param {ASTNode} childNode The AST node child argument being checked
|
|
72
|
-
* @param {Function} cb The callback function
|
|
73
|
-
* @param {Boolean} skipConditional Optional, indicate distinct parsing for conditional nodes
|
|
74
|
-
* @param {Boolean} isolate Optional, set internally to isolate parsing and validation on conditional children
|
|
75
|
-
* @param {Array} ignoredKeys Optional, set object keys which should not be parsed e.g. for `cva`
|
|
76
|
-
* @returns {void}
|
|
77
|
-
*/
|
|
78
|
-
function parseNodeRecursive(rootNode, childNode, cb, skipConditional = false, isolate = false, ignoredKeys = []) {
|
|
79
|
-
// TODO allow vue non litteral
|
|
80
|
-
let originalClassNamesValue
|
|
81
|
-
let classNames
|
|
82
|
-
if (childNode === null) {
|
|
83
|
-
originalClassNamesValue = extractValueFromNode(rootNode);
|
|
84
|
-
({ classNames } = extractClassnamesFromValue(originalClassNamesValue))
|
|
85
|
-
classNames = [... new Set(classNames)]
|
|
86
|
-
if (classNames.length === 0) {
|
|
87
|
-
// Don't run for empty className
|
|
88
|
-
return
|
|
89
|
-
}
|
|
90
|
-
cb(classNames, rootNode)
|
|
91
|
-
} else if (childNode === undefined) {
|
|
92
|
-
// Ignore invalid child candidates (probably inside complex TemplateLiteral)
|
|
93
|
-
return
|
|
94
|
-
} else {
|
|
95
|
-
const forceIsolation = skipConditional ? true : isolate
|
|
96
|
-
let trim = false
|
|
97
|
-
switch (childNode.type) {
|
|
98
|
-
case 'TemplateLiteral':
|
|
99
|
-
childNode.expressions.forEach((exp) => {
|
|
100
|
-
parseNodeRecursive(rootNode, exp, cb, skipConditional, forceIsolation, ignoredKeys)
|
|
101
|
-
})
|
|
102
|
-
childNode.quasis.forEach((quasis) => {
|
|
103
|
-
parseNodeRecursive(rootNode, quasis, cb, skipConditional, isolate, ignoredKeys)
|
|
104
|
-
})
|
|
105
|
-
return
|
|
106
|
-
case 'ConditionalExpression':
|
|
107
|
-
parseNodeRecursive(rootNode, childNode.consequent, cb, skipConditional, forceIsolation, ignoredKeys)
|
|
108
|
-
parseNodeRecursive(rootNode, childNode.alternate, cb, skipConditional, forceIsolation, ignoredKeys)
|
|
109
|
-
return
|
|
110
|
-
case 'LogicalExpression':
|
|
111
|
-
parseNodeRecursive(rootNode, childNode.right, cb, skipConditional, forceIsolation, ignoredKeys)
|
|
112
|
-
return
|
|
113
|
-
case 'ArrayExpression':
|
|
114
|
-
childNode.elements.forEach((el) => {
|
|
115
|
-
parseNodeRecursive(rootNode, el, cb, skipConditional, forceIsolation, ignoredKeys)
|
|
116
|
-
})
|
|
117
|
-
return
|
|
118
|
-
case 'ObjectExpression':
|
|
119
|
-
childNode.properties.forEach((prop) => {
|
|
120
|
-
const isUsedByClassNamesPlugin = rootNode.callee && rootNode.callee.name === 'classnames'
|
|
121
|
-
|
|
122
|
-
if (prop.type === 'SpreadElement') {
|
|
123
|
-
// Ignore spread elements
|
|
124
|
-
return
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (prop.key.type === 'Identifier' && ignoredKeys.includes(prop.key.name)) {
|
|
128
|
-
// Ignore specific keys defined in settings
|
|
129
|
-
return
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
parseNodeRecursive(
|
|
133
|
-
rootNode,
|
|
134
|
-
isUsedByClassNamesPlugin ? prop.key : prop.value,
|
|
135
|
-
cb,
|
|
136
|
-
skipConditional,
|
|
137
|
-
forceIsolation,
|
|
138
|
-
ignoredKeys
|
|
139
|
-
)
|
|
140
|
-
})
|
|
141
|
-
return
|
|
142
|
-
case 'Property':
|
|
143
|
-
parseNodeRecursive(rootNode, childNode.key, cb, skipConditional, forceIsolation, ignoredKeys)
|
|
144
|
-
return
|
|
145
|
-
case 'Literal':
|
|
146
|
-
trim = true
|
|
147
|
-
originalClassNamesValue = childNode.value
|
|
148
|
-
break
|
|
149
|
-
case 'TemplateElement':
|
|
150
|
-
originalClassNamesValue = childNode.value.raw
|
|
151
|
-
break
|
|
152
|
-
}
|
|
153
|
-
({ classNames } = extractClassnamesFromValue(originalClassNamesValue))
|
|
154
|
-
classNames = removeDuplicatesFromArray(classNames)
|
|
155
|
-
if (classNames.length === 0) {
|
|
156
|
-
// Don't run for empty className
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
const targetNode = isolate ? null : rootNode
|
|
160
|
-
cb(classNames, targetNode)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function getTemplateElementPrefix(text, raw) {
|
|
165
|
-
const idx = text.indexOf(raw)
|
|
166
|
-
if (idx === 0) {
|
|
167
|
-
return ''
|
|
168
|
-
}
|
|
169
|
-
return text.split(raw).shift()
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function getTemplateElementSuffix(text, raw) {
|
|
173
|
-
if (text.indexOf(raw) === -1) {
|
|
174
|
-
return ''
|
|
175
|
-
}
|
|
176
|
-
return text.split(raw).pop()
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function getTemplateElementBody(text, prefix, suffix) {
|
|
180
|
-
let arr = text.split(prefix)
|
|
181
|
-
arr.shift()
|
|
182
|
-
let body = arr.join(prefix)
|
|
183
|
-
arr = body.split(suffix)
|
|
184
|
-
arr.pop()
|
|
185
|
-
return arr.join(suffix)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
function findLoc(text, lines, startLine, endLine) {
|
|
189
|
-
for (let i = startLine; i <= endLine; i++) {
|
|
190
|
-
const sourceCodeLine = lines[i - 1]
|
|
191
|
-
const index = sourceCodeLine.indexOf(text)
|
|
192
|
-
if (index !== -1) {
|
|
193
|
-
return {
|
|
194
|
-
start: {
|
|
195
|
-
line: i,
|
|
196
|
-
column: index
|
|
197
|
-
},
|
|
198
|
-
end: {
|
|
199
|
-
line: i,
|
|
200
|
-
column: index + text.length
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return null
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
module.exports = {
|
|
209
|
-
calleeToString,
|
|
210
|
-
extractRangeFromNode,
|
|
211
|
-
extractValueFromNode,
|
|
212
|
-
extractClassnamesFromValue,
|
|
213
|
-
getTemplateElementPrefix,
|
|
214
|
-
getTemplateElementSuffix,
|
|
215
|
-
getTemplateElementBody,
|
|
216
|
-
parseNodeRecursive,
|
|
217
|
-
findLoc
|
|
218
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const exploreConfig = require('explore-config').default
|
|
4
|
-
|
|
5
|
-
const resolveContext = function (context) {
|
|
6
|
-
const settings = Object.assign({
|
|
7
|
-
callees: ['classnames', 'clsx', 'ctl', 'cva', 'cv', 'classVariant', 'styled'],
|
|
8
|
-
ignoredKeys: ['compoundVariants', 'defaultVariants'],
|
|
9
|
-
classMatching: '^class(Name)?$',
|
|
10
|
-
config: 'master.css.*',
|
|
11
|
-
tags: []
|
|
12
|
-
}, context.settings?.['@master/css'])
|
|
13
|
-
const config = settings?.config
|
|
14
|
-
return {
|
|
15
|
-
settings,
|
|
16
|
-
options: context.options[0] || {},
|
|
17
|
-
config: typeof config === 'object' ? config : exploreConfig(settings?.config || '')
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
module.exports = resolveContext
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../lib/rules/class-order')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
const ruleTester = new RuleTester({
|
|
6
|
-
parserOptions: {
|
|
7
|
-
ecmaFeatures: {
|
|
8
|
-
jsx: true,
|
|
9
|
-
},
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
ruleTester.run('class order', rule, {
|
|
14
|
-
valid: [
|
|
15
|
-
{ code: '<h1 className={"bg:black fg:white f:24 m:8 p:8"}>Welcome {name}</h1>' }
|
|
16
|
-
],
|
|
17
|
-
invalid: [
|
|
18
|
-
{
|
|
19
|
-
code: `
|
|
20
|
-
export interface FakePropsInterface {
|
|
21
|
-
readonly name?: string;
|
|
22
|
-
}
|
|
23
|
-
function Fake({
|
|
24
|
-
name = 'yolo'
|
|
25
|
-
}: FakeProps) {
|
|
26
|
-
return (
|
|
27
|
-
<>
|
|
28
|
-
<h1 className={"m:8 bg:black p:8 fg:white f:24"}>Welcome {name}</h1>
|
|
29
|
-
<p>Bye {name}</p>
|
|
30
|
-
</>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
export default Fake;
|
|
34
|
-
`,
|
|
35
|
-
output: `
|
|
36
|
-
export interface FakePropsInterface {
|
|
37
|
-
readonly name?: string;
|
|
38
|
-
}
|
|
39
|
-
function Fake({
|
|
40
|
-
name = 'yolo'
|
|
41
|
-
}: FakeProps) {
|
|
42
|
-
return (
|
|
43
|
-
<>
|
|
44
|
-
<h1 className={"bg:black fg:white f:24 m:8 p:8"}>Welcome {name}</h1>
|
|
45
|
-
<p>Bye {name}</p>
|
|
46
|
-
</>
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
export default Fake;
|
|
50
|
-
`,
|
|
51
|
-
parser: require.resolve('@typescript-eslint/parser'),
|
|
52
|
-
errors: [{ messageId: 'invalidClassOrder' }],
|
|
53
|
-
},
|
|
54
|
-
]
|
|
55
|
-
})
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../lib/rules/class-order')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
const ruleTester = new RuleTester({
|
|
6
|
-
parserOptions: {
|
|
7
|
-
ecmaFeatures: {
|
|
8
|
-
jsx: true,
|
|
9
|
-
},
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
ruleTester.run('svelte class order', rule, {
|
|
14
|
-
valid: [{ code: `<div class="bg:black fg:white f:24 m:8 p:8">Simple, basic</div>` }],
|
|
15
|
-
invalid: [
|
|
16
|
-
{
|
|
17
|
-
code: `<div class="m:8 bg:black p:8 fg:white f:24 {flipped ? 'flipped' : ''}">Enhancing readability</div>`,
|
|
18
|
-
output: `<div class="bg:black fg:white f:24 m:8 p:8 {flipped ? 'flipped' : ''}">Enhancing readability</div>`,
|
|
19
|
-
errors: [{ messageId: 'invalidClassOrder' }],
|
|
20
|
-
filename: 'test.svelte',
|
|
21
|
-
parser: require.resolve('svelte-eslint-parser'),
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
})
|
package/tests/frameworks/vue.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../../lib/rules/class-order')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
const ruleTester = new RuleTester({
|
|
6
|
-
parserOptions: {
|
|
7
|
-
ecmaFeatures: {
|
|
8
|
-
jsx: true,
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
ruleTester.run('vue class order', rule, {
|
|
14
|
-
valid: [{ code: `<div class="bg:black fg:white f:24 m:8 p:8">Simple, basic</div>` }],
|
|
15
|
-
invalid: [
|
|
16
|
-
{
|
|
17
|
-
code: `<template><div class="m:8 bg:black p:8 fg:white f:24">Enhancing readability</div></template>`,
|
|
18
|
-
output: `<template><div class="bg:black fg:white f:24 m:8 p:8">Enhancing readability</div></template>`,
|
|
19
|
-
errors: [{ messageId: 'invalidClassOrder' }],
|
|
20
|
-
filename: 'test.vue',
|
|
21
|
-
parser: require.resolve('vue-eslint-parser'),
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
})
|
package/tests/order.js
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../lib/rules/class-order')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
const ruleTester = new RuleTester({
|
|
6
|
-
parserOptions: {
|
|
7
|
-
ecmaFeatures: {
|
|
8
|
-
jsx: true,
|
|
9
|
-
},
|
|
10
|
-
}
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
ruleTester.run('class order', rule, {
|
|
14
|
-
valid: [
|
|
15
|
-
{
|
|
16
|
-
code: `<div class="bg:black fg:white f:24 m:8 p:8">Simple, basic</div>`,
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
code: `<div class="card mt:20">Traditional class + syntax</div>`,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
code: `<div test="bg:black fg:white f:24 m:8 p:8">Simple, using 'test' prop</div>`,
|
|
23
|
-
options: [
|
|
24
|
-
{
|
|
25
|
-
classMatching: '^test$',
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
},
|
|
29
|
-
],
|
|
30
|
-
invalid: [
|
|
31
|
-
{
|
|
32
|
-
code: `<div class="fg:white f:24 m:8 p:8 bg:black">Classnames will be ordered</div>`,
|
|
33
|
-
output: `<div class="bg:black fg:white f:24 m:8 p:8">Classnames will be ordered</div>`,
|
|
34
|
-
errors: [{ messageId: 'invalidClassOrder' }],
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
code: `
|
|
38
|
-
<div class="
|
|
39
|
-
m:8
|
|
40
|
-
bg:black
|
|
41
|
-
p:8
|
|
42
|
-
fg:white
|
|
43
|
-
f:24
|
|
44
|
-
">
|
|
45
|
-
:)
|
|
46
|
-
</div>`,
|
|
47
|
-
output: `
|
|
48
|
-
<div class="
|
|
49
|
-
bg:black
|
|
50
|
-
fg:white
|
|
51
|
-
f:24
|
|
52
|
-
m:8
|
|
53
|
-
p:8
|
|
54
|
-
">
|
|
55
|
-
:)
|
|
56
|
-
</div>`,
|
|
57
|
-
errors: [{ messageId: 'invalidClassOrder' }],
|
|
58
|
-
parser: require.resolve('@angular-eslint/template-parser'),
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
code: `<div class="flex uppercase m:0 m:0>li text-decoration:none>li>a px:4>li align-items:baseline fg:gray-30>li>a gap-x:28 font:12 font:semibold pb:6>li pt:20 pt:10>li {bb:3|solid|black}>li:has(>.router-link-active) {fg:black}>li:has(>.router-link-active)>a fg:gray-10>li>a:hover box-shadow:none>li>a:focus">Group</div>`,
|
|
62
|
-
output: `<div class="flex uppercase align-items:baseline box-shadow:none>li>a:focus fg:gray-30>li>a fg:gray-10>li>a:hover gap-x:28 font:12 font:semibold {bb:3|solid|black}>li:has(>.router-link-active) {fg:black}>li:has(>.router-link-active)>a m:0 m:0>li pb:6>li pt:20 pt:10>li px:4>li text-decoration:none>li>a">Group</div>`,
|
|
63
|
-
errors: [{ messageId: 'invalidClassOrder' }],
|
|
64
|
-
}
|
|
65
|
-
],
|
|
66
|
-
})
|
package/tests/validation.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
3
|
-
const rule = require('../lib/rules/class-validation')
|
|
4
|
-
const RuleTester = require('eslint').RuleTester
|
|
5
|
-
|
|
6
|
-
new RuleTester({
|
|
7
|
-
parserOptions: {
|
|
8
|
-
ecmaFeatures: {
|
|
9
|
-
jsx: true,
|
|
10
|
-
},
|
|
11
|
-
}
|
|
12
|
-
}).run('invalid', rule, {
|
|
13
|
-
valid: [
|
|
14
|
-
{
|
|
15
|
-
code: `<div class="bg:black fg:white f:24 m:8 p:8">Simple, basic</div>`,
|
|
16
|
-
}
|
|
17
|
-
],
|
|
18
|
-
invalid: [
|
|
19
|
-
{
|
|
20
|
-
code: `<div class="bg:black m:mistake rrr">Simple, basic</div>`,
|
|
21
|
-
errors: [
|
|
22
|
-
{ messageId: 'invalidClass' },
|
|
23
|
-
{ messageId: 'disallowTraditionalClass' }
|
|
24
|
-
],
|
|
25
|
-
options: [
|
|
26
|
-
{
|
|
27
|
-
disallowTraditionalClass: true
|
|
28
|
-
}
|
|
29
|
-
]
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
code: `<div class="bg:black m:mistake rrr">Simple, basic</div>`,
|
|
33
|
-
errors: [
|
|
34
|
-
{ messageId: 'invalidClass' },
|
|
35
|
-
]
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
new RuleTester({
|
|
41
|
-
parserOptions: {
|
|
42
|
-
ecmaFeatures: {
|
|
43
|
-
jsx: true,
|
|
44
|
-
},
|
|
45
|
-
},
|
|
46
|
-
settings: {
|
|
47
|
-
'@master/css': {
|
|
48
|
-
config: {
|
|
49
|
-
styles: { btn: 'block' }
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}).run('invalid', rule, {
|
|
54
|
-
valid: [],
|
|
55
|
-
invalid: [
|
|
56
|
-
{
|
|
57
|
-
code: `<div class="bg:black m:mistake rrr btn">Simple, basic</div>`,
|
|
58
|
-
errors: [
|
|
59
|
-
{ messageId: 'invalidClass' },
|
|
60
|
-
{ messageId: 'disallowTraditionalClass' }
|
|
61
|
-
],
|
|
62
|
-
options: [
|
|
63
|
-
{
|
|
64
|
-
disallowTraditionalClass: true
|
|
65
|
-
}
|
|
66
|
-
]
|
|
67
|
-
},
|
|
68
|
-
],
|
|
69
|
-
})
|