Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(postcss-syntax): update parse function to generate css rules one line per slot(makeStyles)/declaration(makeResetStyles) #548

Merged
merged 12 commits into from
May 7, 2024

Conversation

YuanboXue-Amber
Copy link
Contributor

Background:

parse function was created for linting griffel styles with stylelint. It reads the css-in-js styles, and output a post css AST that can be used by stylelint.

Before:

parse function adjusts the location directly the the returned AST. But it doesn't work well with stylelint.

For example:

import { makeStyles } from "@griffel/react";

export const useStyles = makeStyles({
  root: {
    color: "#111",
  },
});

parse maps the location of node color: '#111' to { line: 4, column: 2, endLine: 6, endColumn: 3 }, which is the location of entire root slot. When stylelint lints the AST and tries to give a warning on "#111", it takes the start location and adds length of the 4-character string "#111" on top. The result warning location is { line: 4, column: 2, endLine: 4, endColumn: 6 }, which is not the best.

To guarantee accurate result from stylelint, the location in AST must match the original css source.

After:

parse function does:

  1. generates CSS rules: each slot in makeStyles and each makeResetStyles will be one line in the output.
  2. call postcss.parse on the generated rule to get AST
  3. walk the AST. The slot name for each node can be found based on the line number in css source. With slot name known, each node is attached with information about the slot location from the original js source.

When stylelint lint the AST, it gives warnings based on the location in css source. We can use stylelint processors to re-map the warnings to slot location in original js.

Here's an example processor:

import {
  GRIFFEL_DECLARATOR_LOCATION_RAW,
  GRIFFEL_SLOT_LOCATION_RAW,
} from "@griffel/postcss-syntax";

/** @type {import("stylelint").Processor} */
export default function () {
  return {
    name: "griffel-post-processor",

    postprocess(result, root) {
      const updatedWarnings = result.warnings.map((warning) => {
        let updatedWarning = { ...warning };

        root?.walk((node) => {
          const cssInJSLocation =
            node.raws[GRIFFEL_DECLARATOR_LOCATION_RAW] ||
            node.raws[GRIFFEL_SLOT_LOCATION_RAW];

          if (cssInJSLocation) {
            const { start, end } = node.source;
            if (
              start.line <= warning.line &&
              end.line >= warning.line &&
              start.column <= warning.column &&
              end.column >= warning.column
            ) {
              updatedWarning = {
                ...updatedWarning,
                line: cssInJSLocation.start.line,
                column: cssInJSLocation.start.column,
                endLine: cssInJSLocation.end.line,
                endColumn: cssInJSLocation.end.column,
              };
              return false;
            }
          }
        });

        return updatedWarning;
      });

      result.warnings = updatedWarnings;
    },
  };
}

With the above processor, stylelint result has meaningful location:

import stylelint from "stylelint";

const code = `import { makeStyles } from "@griffel/react";

export const useStyles = makeStyles({
  root: {
    color: "#111",
  },
});`;

(async function main() {
  const data = await stylelint.lint({
    code,
    config: {
      processors: ["./griffel-post-processor.js"],
      rules: {
        "color-no-hex": [true],
      },
      customSyntax: "@griffel/postcss-syntax",
    },
  });

  console.log("final warnings", data.results[0].warnings);
  // Result from console:
  //  [
  //   {
  //     line: 4,
  //     column: 2,
  //     endLine: 6,
  //     endColumn: 3,
  //     rule: 'color-no-hex',
  //     severity: 'error',
  //     text: 'Unexpected hex color "#111" (color-no-hex)'
  //   }
  // ]
})();

Related

stylelint/stylelint#7567
stylelint/stylelint#7568

@YuanboXue-Amber YuanboXue-Amber changed the title feat(postcss-syntax): update parse function feat(postcss-syntax): update parse function to generate css rules one line per slot(makeStyles)/declaration(makeResetStyles) Apr 24, 2024
@YuanboXue-Amber YuanboXue-Amber marked this pull request as ready for review April 24, 2024 11:22
@YuanboXue-Amber YuanboXue-Amber requested a review from a team as a code owner April 24, 2024 11:22
@YuanboXue-Amber YuanboXue-Amber merged commit 8f670a5 into microsoft:main May 7, 2024
4 checks passed
@YuanboXue-Amber YuanboXue-Amber deleted the parse branch May 7, 2024 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants