diff --git a/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.interface.ts b/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.interface.ts index 159cab9..e8495a2 100644 --- a/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.interface.ts +++ b/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.interface.ts @@ -1,3 +1,4 @@ +import { IRuleset } from "src/1_entities/Ruleset"; import RulesetsListBuilder, { IRulesetsListBuilder, } from "../../1_entities/RulesetsListBuilder"; @@ -6,6 +7,7 @@ export interface Props extends IRulesetsListBuilder.DTO {} export interface DTO { values: ValuesMap; + definitions: IRuleset.DTO[]; } export type ClassnamesMap = IRulesetsListBuilder.ClassnamesMap; diff --git a/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.test.ts b/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.test.ts index 22c3cf3..71dfef9 100644 --- a/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.test.ts +++ b/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.test.ts @@ -7,6 +7,8 @@ const toString = (rs: IRuleset.DTO[]) => const basic: IBuildRulesets.Props = { variantsMap: {}, classnamesMap: { + width: "w-$0", + filter: "ftr_$0", filterCompound: "ftr~", filterBlur: "~bl_$0", @@ -50,6 +52,8 @@ const basic: IBuildRulesets.Props = { transformPerspective: "~prs_$0", }, declarationsMap: { + width: "width: $0;", + filter: "filter: $0;", filterCompound: "filter: blur(var(--filterBlur)) brightness(var(--filterBrightness)) contrast(var(--filterContrast)) drop-shadow(var(--filterDropShadow)) grayscale(var(--filterGrayscale)) hue-rotate(var(--filterHueRotate)) invert(var(--filterInvert)) opacity(var(--filterOpacity)) saturate(var(--filterSaturate)) sepia(var(--filterSepia));", @@ -122,13 +126,27 @@ const withVariants: IBuildRulesets.Props = { describe("BuildRulesets usecase", () => { it("should not crash if nothing is provided", () => { const build = BuildRulesets.create(basic); - const res = build.exec({ values: {} }); + const res = build.exec({ values: {}, definitions: [] }); expect(res).toEqual([]); }); + it("should build from values and definitions", () => { + const build = BuildRulesets.create(basic); + const res = build.exec({ + values: { width: { "20": "20px" } }, + definitions: [{ classname: "height-sm", declarations: "height: 12px;" }], + }); + + expect(toString(res)).toEqual([ + ".w-20 { width: 20px; }", + ".height-sm { height: 12px; }", + ]); + }); + it("should build font size rulesets", () => { const build = BuildRulesets.create(basic); const res = build.exec({ + definitions: [], values: { fontSize: { "20": "20px", "2em": "2em", md: "16px/24px" }, }, @@ -144,6 +162,7 @@ describe("BuildRulesets usecase", () => { it("should build flex grid rulesets", () => { const build = BuildRulesets.create(basic); const res = build.exec({ + definitions: [], values: { flexGrid: { cols: 6 }, }, @@ -164,6 +183,7 @@ describe("BuildRulesets usecase", () => { it("should build flex grid rulesets with gutters", () => { const build = BuildRulesets.create(basic); const res = build.exec({ + definitions: [], values: { flexGrid: { cols: 12, @@ -172,6 +192,7 @@ describe("BuildRulesets usecase", () => { }, }, }); + // prettier-ignore expect(toString(res)).toEqual([ ".fxrow { display: flex; margin-left: -5px; margin-right: -5px; }", @@ -200,6 +221,7 @@ describe("BuildRulesets usecase", () => { const build = BuildRulesets.create(basic); const res = build.exec({ + definitions: [], values: { transform: { custom: "translate(120px, 50%)", @@ -260,6 +282,7 @@ describe("BuildRulesets usecase", () => { const build = BuildRulesets.create(basic); const res = build.exec({ + definitions: [], values: { filterCompound: {}, filter: { diff --git a/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.ts b/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.ts index d56d3b8..10fd89c 100644 --- a/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.ts +++ b/packages/rececss-core/src/2_usecases/BuildRulesets/BuildRulesets.ts @@ -36,6 +36,10 @@ export default class BuildRulesets { ); }); + dto.definitions.forEach((dto) => { + this.builder.addRulesetFromDTO(dto); + }); + return this.builder.getResult(); } } diff --git a/packages/rececss-core/src/3_adapters/StylesheetsController/StylesheetsController.ts b/packages/rececss-core/src/3_adapters/StylesheetsController/StylesheetsController.ts index 88c037d..a0848ba 100644 --- a/packages/rececss-core/src/3_adapters/StylesheetsController/StylesheetsController.ts +++ b/packages/rececss-core/src/3_adapters/StylesheetsController/StylesheetsController.ts @@ -16,6 +16,7 @@ export default class StylesheetsController { const rulesetsProps = this.io.getRulesetsBuildProps(); const rulesets = BuildRulesets.create(rulesetsProps).exec({ values: this.io.getRulesetsValues(), + definitions: this.io.getRulesetsDefinitions(), }); const assetsProps = this.io.getAssetsGenerationProps(); diff --git a/packages/rececss-core/src/3_adapters/interfaces.ts b/packages/rececss-core/src/3_adapters/interfaces.ts index 4f6c991..9b74e5d 100644 --- a/packages/rececss-core/src/3_adapters/interfaces.ts +++ b/packages/rececss-core/src/3_adapters/interfaces.ts @@ -1,3 +1,4 @@ +import { IRuleset } from "src/1_entities/Ruleset"; import { IGenerateStylesheetAssets } from "../2_usecases/GenerateStylesheetAssets"; import { IBuildRulesets } from "../2_usecases/BuildRulesets"; @@ -5,6 +6,7 @@ export interface IInputOutput { getAssetsGenerationProps(): IGenerateStylesheetAssets.Props; getRulesetsBuildProps(): IBuildRulesets.Props; getRulesetsValues(): IBuildRulesets.DTO["values"]; + getRulesetsDefinitions(): IRuleset.DTO[]; getMediaQueries: () => Record; outputAssets(assets: { name: string; contents: string }[]): Promise; } diff --git a/packages/rececss-core/src/4_infrastructures/config/Config.interfaces.ts b/packages/rececss-core/src/4_infrastructures/config/Config.interfaces.ts index f7a69bf..38b10de 100644 --- a/packages/rececss-core/src/4_infrastructures/config/Config.interfaces.ts +++ b/packages/rececss-core/src/4_infrastructures/config/Config.interfaces.ts @@ -1,3 +1,4 @@ +import { IRuleset } from "../../1_entities/Ruleset"; import { IBuildRulesets } from "../../2_usecases/BuildRulesets"; export interface Props { @@ -35,6 +36,7 @@ export interface DTO { values: CreatorFn | RawValues; variants?: CreatorFn | Variants; associations?: CreatorFn | Associations; + definitions?: IRuleset.DTO[]; } type ValueOf = T[keyof T]; diff --git a/packages/rececss-core/src/4_infrastructures/config/Config.test.ts b/packages/rececss-core/src/4_infrastructures/config/Config.test.ts index 4d457f0..ab67754 100644 --- a/packages/rececss-core/src/4_infrastructures/config/Config.test.ts +++ b/packages/rececss-core/src/4_infrastructures/config/Config.test.ts @@ -84,6 +84,16 @@ describe("Config", () => { expect(config.getVariantSeparator()).toBe(":"); }); + test("definitions getter", () => { + const config = configBasic.create(dto); + expect(config.getRulesetDefinitions()).toEqual([ + { + classname: "width-20px", + declarations: "width: 20px;", + }, + ]); + }); + test("classnames getter", () => { const classesConfig = configBasic.create({ output: { path: "" }, diff --git a/packages/rececss-core/src/4_infrastructures/config/Config.ts b/packages/rececss-core/src/4_infrastructures/config/Config.ts index 4d08930..51910e6 100644 --- a/packages/rececss-core/src/4_infrastructures/config/Config.ts +++ b/packages/rececss-core/src/4_infrastructures/config/Config.ts @@ -115,6 +115,10 @@ export default class Config { return result; } + getRulesetDefinitions() { + return this.dto.definitions || []; + } + private parseRuleValue(rule?: any): Record { if (!rule) return {}; return Object.keys(rule).reduce((acc, key) => { diff --git a/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.test.ts b/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.test.ts index 1333794..f855707 100644 --- a/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.test.ts +++ b/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.test.ts @@ -1,27 +1,9 @@ import path from "path"; import IO from "./ConfigFileSystemIO"; +const configDto = require("../../../tests/__fixtures__/rececss.config"); const writeFiles = jest.fn(() => Promise.resolve()); -const configDto = { - output: { - path: "./website/styles", - filename: "rececss", - extension: "css", - splitByMedia: false, - purge: { content: ["./website/pages/**/*.js"] }, - }, - media: { - md: "only screen and (min-width: 768px)", - lg: "only screen and (min-width: 1024px)", - }, - separator: { - media: ":", - variant: ":", - }, - values: {}, -}; - describe("ConfigFileSystemIO", () => { it("should return media queries", () => { const io = IO.create(configDto, writeFiles); @@ -42,13 +24,21 @@ describe("ConfigFileSystemIO", () => { }); }); + it("should return ruleset definitions", () => { + const io = IO.create(configDto, writeFiles); + const defs = io.getRulesetsDefinitions(); + expect(defs).toEqual([ + { classname: "width-20px", declarations: "width: 20px;" }, + ]); + }); + it("should return css processor input", () => { const io = IO.create(configDto, writeFiles); const input = io.getCSSProccesorInput(); expect(input).toEqual({ content: ["./website/pages/**/*.js"] }); }); - it("should output assets by calling fs.writeFiles with proper filepaths", async () => { + it("should output assets by calling fs.writeFiles with proper filepaths", () => { const io = IO.create(configDto, writeFiles); io.outputAssets([{ name: "some", contents: "contents" }]); expect(writeFiles).toHaveBeenCalledWith([ diff --git a/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.ts b/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.ts index 5955dad..ba5a620 100644 --- a/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.ts +++ b/packages/rececss-core/src/4_infrastructures/io/ConfigFileSystemIO.ts @@ -23,6 +23,10 @@ export default class ConfigFileSystemIO implements IInputOutput { return this.config.getRulesetsValues(); } + getRulesetsDefinitions() { + return this.config.getRulesetDefinitions(); + } + getRulesetsBuildProps() { return { classnamesMap: this.config.getRulesetsClassnames(), diff --git a/packages/rececss-core/tests/__fixtures__/rececss.config.js b/packages/rececss-core/tests/__fixtures__/rececss.config.js index c1f52de..2452f93 100644 --- a/packages/rececss-core/tests/__fixtures__/rececss.config.js +++ b/packages/rececss-core/tests/__fixtures__/rececss.config.js @@ -15,4 +15,10 @@ module.exports = { variant: ":", }, values: {}, + definitions: [ + { + classname: "width-20px", + declarations: "width: 20px;", + }, + ], }; diff --git a/packages/rececss-core/tests/__mocks__/io.ts b/packages/rececss-core/tests/__mocks__/io.ts index f9574c9..f382ee6 100644 --- a/packages/rececss-core/tests/__mocks__/io.ts +++ b/packages/rececss-core/tests/__mocks__/io.ts @@ -6,6 +6,7 @@ const ioMock: IInputOutput = { outputAssets: jest.fn(), getRulesetsBuildProps: jest.fn(), getRulesetsValues: jest.fn(() => ({})), + getRulesetsDefinitions: jest.fn(() => []), }; export default ioMock;