Skip to content

Commit

Permalink
Tagged
Browse files Browse the repository at this point in the history
  • Loading branch information
rnyell committed Nov 11, 2024
1 parent fa8070d commit 05c70bf
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 79 deletions.
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**/*.md
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-contains",
"version": "0.0.1",
"version": "0.1.0",
"description": "A PostCSS plugin to styles selectors based on specific declaration or property.",
"keywords": [
"postcss",
Expand All @@ -27,7 +27,7 @@
"test": "vitest run",
"ci": "npm run build && npm run check-format && npm run test"
},
"dependencies": {
"peerDependencies": {
"postcss": "^8.4.47"
},
"devDependencies": {
Expand Down
18 changes: 10 additions & 8 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@ The `@contains` at-rule targets elements and selectors when they _contain_:
- A specific property (e.g. `position` or `margin`)
- A specific declaration (property-value pair, e.g. `display: grid`)


## Installation

```sh
npm install postcss-contains --save-dev
```


## Usage

```js
// postcss.config.js
import postcssContains from "postcss-contains";
import postcssContains from "postcss-contains"

export default {
plugins: [postcssContains],
};
}
```

```css
Expand Down Expand Up @@ -86,6 +88,7 @@ div {
}
```


### Duplications

When two `@contains` rules target the same property or declaration, their styles will merge by default.
Expand Down Expand Up @@ -134,6 +137,7 @@ div {

See [options](#options) for more.


### Specificity

"Property-value" matches considered with a specificity so they take precedence over "property-only" matches.
Expand Down Expand Up @@ -169,6 +173,7 @@ span {
}
```


## Options

#### `duplication`
Expand Down Expand Up @@ -236,16 +241,13 @@ div {

```css
/* a */
@contains (color) {
}
@contains (color) {}

/* b */
@contains (color: red) {
}
@contains (color: red) {}

/* c */
@contains (color: red) {
}
@contains (color: red) {}
```

More examples are provided [here](./test/exmaples.md).
128 changes: 63 additions & 65 deletions src/contains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,87 +179,85 @@ export default class Contains {
}

// 1) collecting all @contains: conditions and their declarations
collect(root: Root, result: Result) {
root.walkAtRules("contains", (atRule: AtRule) => {
const params = getParams(atRule.params);
const overrides = atRule.params.startsWith("overrides");

if (/\n/.test(atRule.params)) {
atRule.warn(
result,
"It's better to not use new lines inside @contains params.",
);
}
collect(atRule: AtRule, result: Result) {
const params = getParams(atRule.params);
const overrides = atRule.params.startsWith("overrides");

if (/\n/.test(atRule.params)) {
atRule.warn(
result,
"It's better to not use new lines inside @contains params.",
);
}

if (!atRule.nodes) {
throw new Error(
`@contains has no styles (provided no curly brackets).\n ${atRule.toString()}`,
);
}
if (!atRule.nodes) {
throw atRule.error(
`@contains has no styles (provided no curly brackets).\n ${atRule.toString()}`,
);
}

if (atRule.nodes.length === 0) {
atRule.warn(result, `The @contains was empty; it provides no styles.`);
}
if (atRule.nodes.length === 0) {
atRule.warn(result, `The @contains was empty; it provides no styles.`);
}

const isInvalidType = atRule.nodes.some(
(child) => child.type === "rule" || child.type === "atrule",
const isInvalidType = atRule.nodes.some(
(child) => child.type === "rule" || child.type === "atrule",
);

if (isInvalidType) {
throw atRule.error(
`rules and at-rules can not be nested inside @contains.\n ${atRule.toString()}`,
);
}

if (isInvalidType) {
throw new Error(
`rules and at-rules can not be nested inside @contains.\n ${atRule.toString()}`,
if (params.includes(":")) {
const { property, value } = extract(params, "pair");

if (!property || !value) {
throw atRule.error(
`Something went wrong on \t ${atRule.toString()} \n\t >>> property: ${property} - value: ${value}`,
);
}

if (params.includes(":")) {
const { property, value } = extract(params, "pair");

if (!property || !value) {
throw new Error(
`Something went wrong on \t ${atRule.toString()} \n\t >>> property: ${property} - value: ${value}`,
);
}

const variant: "pair" | "single" = "pair";
const declarations = new Map<string, string>();
const variant: "pair" | "single" = "pair";
const declarations = new Map<string, string>();

for (const node of atRule.nodes) {
if (node.type === "decl") {
const { prop, value, important } = node;
// const declaration = new Declaration({ prop, value, important });
declarations.set(prop, value);
}
for (const node of atRule.nodes) {
if (node.type === "decl") {
const { prop, value, important } = node;
// const declaration = new Declaration({ prop, value, important });
declarations.set(prop, value);
}
}

const bucket = { value, variant, overrides, declarations };
this.add(property, bucket);
atRule.remove();
return;
} else {
const { property } = extract(params, "single");
const bucket = { value, variant, overrides, declarations };
this.add(property, bucket);
atRule.remove();
return;
} else {
const { property } = extract(params, "single");

if (!property) {
throw new Error(
`Something went wrong on \t ${atRule.toString()} \n\t >>> property: ${property}`,
);
}
if (!property) {
throw atRule.error(
`Something went wrong on \t ${atRule.toString()} \n\t >>> property: ${property}`,
);
}

const variant: "pair" | "single" = "single";
const declarations = new Map<string, string>();
const variant: "pair" | "single" = "single";
const declarations = new Map<string, string>();

for (const node of atRule.nodes) {
if (node.type === "decl") {
const { prop, value, important } = node;
declarations.set(prop, value);
}
for (const node of atRule.nodes) {
if (node.type === "decl") {
const { prop, value, important } = node;
declarations.set(prop, value);
}

const bucket = { value: null, variant, overrides, declarations };
this.add(property, bucket);
atRule.remove();
return;
}
});

const bucket = { value: null, variant, overrides, declarations };
this.add(property, bucket);
atRule.remove();
return;
}
}

add(property: string, bucket: Bucket) {
Expand Down
6 changes: 4 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@ const plugin: PluginCreator<PluginOptions> = (opts?: PluginOptions) => {
return {
postcssPlugin: "postcss-contains",

Once(root, { result }) {
contains.collect(root, result);
AtRule: {
contains(atRule, { result }) {
contains.collect(atRule, result);
},
},

Rule(rule) {
Expand Down
2 changes: 1 addition & 1 deletion test/exmaples.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
- No property or declaration passed to @contains

```css
@Contains() {
@Contains () {
/* styles */
}
```
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
"outDir": "dist",
"sourceMap": true
},
"exclude": ["dist", "test"]
"include": ["src"]
}

0 comments on commit 05c70bf

Please sign in to comment.