Commit 24d8fad1 authored by David Sveningsson's avatar David Sveningsson

feat(rules): refactor `parseStyle` from `element-case` and `attr-case`

parent be7d6928
import { HtmlElement } from "../dom";
import { AttributeEvent } from "../event";
import { Rule, RuleDocumentation, ruleDocumentationUrl } from "../rule";
import { CaseStyle } from "./helper/case-style";
const defaults = {
style: "lowercase",
......@@ -8,12 +9,11 @@ const defaults = {
};
class AttrCase extends Rule {
private pattern: RegExp;
private lettercase: string;
private style: CaseStyle;
public constructor(options: object) {
super(Object.assign({}, defaults, options));
[this.pattern, this.lettercase] = parseStyle(this.options.style);
this.style = new CaseStyle(this.options.style, "attr-case");
}
public documentation(): RuleDocumentation {
......@@ -37,10 +37,10 @@ class AttrCase extends Rule {
}
const letters = event.key.replace(/[^a-z]+/gi, "");
if (!letters.match(this.pattern)) {
if (!this.style.match(letters)) {
this.report(
event.target,
`Attribute "${event.key}" should be ${this.lettercase}`
`Attribute "${event.key}" should be ${this.style.name}`
);
}
});
......@@ -55,19 +55,4 @@ class AttrCase extends Rule {
}
}
function parseStyle(style: string): [RegExp, string] {
switch (style.toLowerCase()) {
case "lowercase":
return [/^[a-z]*$/, "lowercase"];
case "uppercase":
return [/^[A-Z]*$/, "uppercase"];
case "pascalcase":
return [/^[A-Z][A-Za-z]*$/, "PascalCase"];
case "camelcase":
return [/^[a-z][A-Za-z]*$/, "camelCase"];
default:
throw new Error(`Invalid style "${style}" for "attr-case" rule`);
}
}
module.exports = AttrCase;
import { sliceLocation } from "../context";
import { TagOpenEvent } from "../event";
import { Rule, RuleDocumentation, ruleDocumentationUrl } from "../rule";
import { CaseStyle } from "./helper/case-style";
const defaults = {
style: "lowercase",
};
class ElementCase extends Rule {
private pattern: RegExp;
private lettercase: string;
private style: CaseStyle;
public constructor(options: object) {
super(Object.assign({}, defaults, options));
[this.pattern, this.lettercase] = parseStyle(this.options.style);
this.style = new CaseStyle(this.options.style, "element-case");
}
public documentation(): RuleDocumentation {
......@@ -25,11 +25,11 @@ class ElementCase extends Rule {
public setup(): void {
this.on("tag:open", (event: TagOpenEvent) => {
const letters = event.target.tagName.replace(/[^a-z]+/gi, "");
if (!letters.match(this.pattern)) {
if (!this.style.match(letters)) {
const location = sliceLocation(event.location, 1);
this.report(
event.target,
`Element "${event.target.tagName}" should be ${this.lettercase}`,
`Element "${event.target.tagName}" should be ${this.style.name}`,
location
);
}
......@@ -37,19 +37,4 @@ class ElementCase extends Rule {
}
}
function parseStyle(style: string): [RegExp, string] {
switch (style.toLowerCase()) {
case "lowercase":
return [/^[a-z]*$/, "lowercase"];
case "uppercase":
return [/^[A-Z]*$/, "uppercase"];
case "pascalcase":
return [/^[A-Z][A-Za-z]*$/, "PascalCase"];
case "camelcase":
return [/^[a-z][A-Za-z]*$/, "camelCase"];
default:
throw new Error(`Invalid style "${style}" for "element-case" rule`);
}
}
module.exports = ElementCase;
import { CaseStyle } from "./case-style";
it.each`
style | text
${"lowercase"} | ${"foo"}
${"uppercase"} | ${"FOO"}
${"camelcase"} | ${"foo"}
${"camelcase"} | ${"fooBar"}
${"pascalcase"} | ${"Foo"}
${"pascalcase"} | ${"FooBar"}
`('style "$style" should match "$text"', ({ style, text }) => {
expect.assertions(1);
const cs = new CaseStyle(style, "test-case");
expect(cs.match(text)).toBeTruthy();
});
it.each`
style | text
${"lowercase"} | ${"FOO"}
${"uppercase"} | ${"foo"}
${"camelcase"} | ${"Foo"}
${"camelcase"} | ${"FooBar"}
${"pascalcase"} | ${"foo"}
${"pascalcase"} | ${"fooBar"}
`('style "$style" should not match "$text"', ({ style, text }) => {
expect.assertions(1);
const cs = new CaseStyle(style, "test-case");
expect(cs.match(text)).toBeFalsy();
});
it("should throw exception for unknown styles", () => {
expect.assertions(1);
expect(() => {
return new CaseStyle("unknown-style", "test-case");
}).toThrow('Invalid style "unknown-style" for "test-case" rule');
});
/**
* Represents casing for a name, e.g. lowercase, uppercase, etc.
*/
export class CaseStyle {
public name: string;
private pattern: RegExp;
/**
* @param style - Name of a valid case style.
*/
public constructor(style: string, ruleId: string) {
[this.pattern, this.name] = this.parseStyle(style, ruleId);
}
/**
* Test if a text matches this case style.
*/
public match(text: string): boolean {
return !!text.match(this.pattern);
}
private parseStyle(style: string, ruleId: string): [RegExp, string] {
switch (style.toLowerCase()) {
case "lowercase":
return [/^[a-z]*$/, "lowercase"];
case "uppercase":
return [/^[A-Z]*$/, "uppercase"];
case "pascalcase":
return [/^[A-Z][A-Za-z]*$/, "PascalCase"];
case "camelcase":
return [/^[a-z][A-Za-z]*$/, "camelCase"];
default:
throw new Error(`Invalid style "${style}" for "${ruleId}" rule`);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment