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

Possibility to transfer it nicely when using tailwindcss #413

Open
vcharov opened this issue Sep 8, 2022 · 15 comments
Open

Possibility to transfer it nicely when using tailwindcss #413

vcharov opened this issue Sep 8, 2022 · 15 comments

Comments

@vcharov
Copy link

vcharov commented Sep 8, 2022

Request / Idea

It would be nice to be able to transfer it nicely when using tailwindcss. This would make the code much more readable

Input

MenuButton(
  class=["relative z-10 flex items-center w-11 gap-2 whitespace-nowrap text-ellipsis overflow-hidden text-xs", "lg:gap-6"]
)

Expected Output

MenuButton(
  class=[
    "relative z-10 flex items-center w-11 gap-2 whitespace-nowrap text-ellipsis overflow-hidden text-xs",
    "lg:gap-6"
  ]
)
@Shinigami92
Copy link
Member

Is it expected / correct that you didn't use quotes but class=[ ... (instead of class="[ ...)
If yes I'm afraid you are running into the same problem as many other users did before you => #66

This is a limitation of pug itself and is currently not really handleable 😔

@vcharov
Copy link
Author

vcharov commented Sep 8, 2022

you can write it that way, but it looks strange

MenuButton(
  class={
    "relative z-10 flex items-center w-11 gap-2 whitespace-nowrap text-ellipsis overflow-hidden text-xs": true,
    "lg:gap-6": true
  }
)

@Shinigami92
Copy link
Member

class={ results in the same issue
It's the parser that has the problem, not the formatter

@vcharov
Copy link
Author

vcharov commented Sep 8, 2022

Maybe there is a way not to make a fix for these cases?

header.header-module(
  class=[
    "bg-off-white shadow-main-header flex items-center gap-x-2 py-2 px-4",
    "lg:px-8"
  ]
)

Снимок 2022-09-08 17 45 12

@Shinigami92
Copy link
Member

I'm open to PRs
Please open a PR and add a test, you can orientate yourself on any test inside https://github.com/prettier/plugin-pug/tree/main/tests/issues
Happy to review your solution

@vcharov
Copy link
Author

vcharov commented Sep 9, 2022

Did I understand you correctly, there is no such rule at the moment?

@Shinigami92
Copy link
Member

Did I understand you correctly, there is no such rule at the moment?

You are in the repo for the pug formatter
A formatter doesn't have rules, but options
The rule that got triggered in your screenshot is coming from https://www.npmjs.com/package/eslint-plugin-prettier-vue

@vcharov
Copy link
Author

vcharov commented Sep 9, 2022

thanks for the help

@vcharov
Copy link
Author

vcharov commented Sep 13, 2022

Please advise where is the parsing code

@vcharov vcharov reopened this Sep 13, 2022
@Shinigami92
Copy link
Member

Please have a look into this: pugjs/pug#3214

@vcharov
Copy link
Author

vcharov commented Sep 13, 2022

The point is that the parser works correctly, the expected code is valid and works correctly. But plugin:prettier-vue/recommended prohibits such hyphenation

package.json

{
  "name": "spa",
  "version": "0.0.1",
  "main": "src/main.ts",
  "scripts": {
    "watch": "vite --host handlarfinans.local --port 8888",
    "dev": "vue-tsc --noEmit && vite build",
    "prod": "vue-tsc --noEmit && vite build",
    "lint": "echo null",
    "lint:disabled": "npm run lint:js",
    "lint:fix": "npm run lint:js -- --fix",
    "lint:js": "cross-env NODE_ENV=production eslint --ext .js,.vue --ignore-path .gitignore src"
  },
  "dependencies": {
    "@bundled-es-modules/axios": "^0.27.2",
    "@headlessui/vue": "^1.6.7",
    "@vueuse/head": "^0.7.9",
    "axios": "^0.27.2",
    "pinia": "^2.0.18",
    "vue": "^3.2.37",
    "vue-i18n": "^9.2.2",
    "vue-router": "^4.1.3",
    "vue3-mq": "^3.1.0"
  },
  "devDependencies": {
    "@prettier/plugin-pug": "^2.2.0",
    "@tailwindcss/aspect-ratio": "^0.4.0",
    "@tailwindcss/forms": "^0.5.2",
    "@tailwindcss/line-clamp": "^0.4.0",
    "@tailwindcss/typography": "^0.5.4",
    "@typescript-eslint/eslint-plugin": "^5.32.0",
    "@typescript-eslint/parser": "^5.33.0",
    "@vitejs/plugin-vue": "^3.0.0",
    "autoprefixer": "^10.4.8",
    "cross-env": "^7.0.3",
    "eslint": "^8.21.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier-vue": "^4.2.0",
    "eslint-plugin-security": "^1.5.0",
    "eslint-plugin-tailwindcss": "^3.6.0",
    "eslint-plugin-vue": "^9.3.0",
    "eslint-plugin-vue-pug": "^0.5.4",
    "husky": "^8.0.1",
    "postcss": "^8.4.14",
    "pug": "^3.0.2",
    "stylelint": "^14.9.1",
    "stylelint-config-rational-order": "^0.1.2",
    "stylelint-config-recommended-vue": "^1.4.0",
    "stylelint-config-standard": "^26.0.0",
    "tailwind-scrollbar": "^2.0.1",
    "tailwindcss": "^3.1.8",
    "tailwindcss-debug-screens": "^2.2.1",
    "typescript": "^4.6.4",
    "unplugin-auto-import": "^0.11.1",
    "unplugin-vue-components": "^0.22.0",
    "vite": "^3.0.0",
    "vite-plugin-pages": "^0.25.0",
    "vite-plugin-svg-icons": "^2.0.1",
    "vite-plugin-vue-layouts": "0.6.0",
    "vue-eslint-parser": "^9.0.3",
    "vue-tsc": "^0.38.4"
  }
}

.eslintrc.js

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:vue/vue3-recommended',
    'plugin:vue-pug/vue3-recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:prettier-vue/recommended',
    'plugin:security/recommended',
    'plugin:tailwindcss/recommended',
    '.eslintrc-auto-import.json',
  ],
  parser: 'vue-eslint-parser',
  parserOptions: {
    parser: '@typescript-eslint/parser',
    sourceType: 'module',
    ecmaVersion: 2021,
  },
  rules: {
    //- prettier
    'prettier-vue/prettier': [
      'error',
      {
        singleQuote: true,
        semi: false,
        eol: 'lf',
        printWidth: 80,

        //- Prettier: pug
        pugPrintWidth: 80,
        pugFramework: 'vue',
        pugSingleQuote: false,
        pugAttributeSeparator: 'none',
        pugWrapAttributesThreshold: 1,
        pugEmptyAttributesForceQuotes: ['class', 'type', 'style', 'v-model'],
        pugClassNotation: 'as-is',
        pugEmptyAttributes: 'none',
      },
    ],

    //- pug
    'vue-pug/no-pug-control-flow': 'error',

    //- eslint
    'no-var': 'error',
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'comma-dangle': ['error', 'only-multiline'],
    'id-length': [2, { exceptions: ['i', 'j', '_', 't'] }],
    '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '_' }],
    'vue/block-lang': [
      'error',
      {
        template: { lang: 'pug' },
      },
    ],
    'vue/component-api-style': ['error', ['script-setup']],
    'vue/html-button-has-type': [
      'error',
      {
        button: true,
        submit: true,
        reset: true,
      },
    ],
    'vue/component-name-in-template-casing': [
      'error',
      'PascalCase',
      {
        registeredComponentsOnly: false,
      },
    ],
    'vue/custom-event-name-casing': 'error',
    'vue/define-macros-order': 'error',
    'vue/no-empty-component-block': 'error',
    'vue/no-multiple-objects-in-class': 'error',
    'vue/no-restricted-call-after-await': 'error',
    'vue/no-static-inline-styles': 'error',
    'vue/no-template-target-blank': 'error',
    'vue/no-undef-properties': 'error',
    'vue/no-unsupported-features': ['error', { version: '^3.2.37' }],
    'vue/no-useless-mustaches': 'error',
    'vue/no-useless-v-bind': 'error',
    'vue/padding-line-between-blocks': 'error',
    'vue/prefer-true-attribute-shorthand': 'error',
    'vue/require-emit-validator': 'error',
    'vue/v-for-delimiter-style': 'error',
    'vue/v-on-function-call': 'error',
    'vue/component-tags-order': [
      'error',
      { order: ['script:not([setup])', 'script[setup]', 'template', 'style'] },
    ],

    //- tailwindcss
    'tailwindcss/no-custom-classname': 'off',
    'tailwindcss/classnames-order': 'off',
  },
  globals: {
    defineProps: 'readonly',
    defineEmits: 'readonly',
    defineExpose: 'readonly',
    withDefaults: 'readonly',
  },
}

@Shinigami92
Copy link
Member

As I said: please open a PR and try to tackle this issue on your own
I'm happy to review

@Shinigami92
Copy link
Member

Some hints:
Please have a look at this method:

private class(token: ClassToken): void {

And please add a test in https://github.com/prettier/plugin-pug/tree/main/tests/issues

From there I might help further, but please first put some effort on your own into this

@Shinigami92
Copy link
Member

Home now and I looked into the code and started to debug a bit

Seems like you may have luck, I'm not promising anything but it might be you are not affected directly be the parsers problem

So around here:

plugin-pug/src/printer.ts

Lines 934 to 935 in d520345

if (typeof token.val === 'string') {
if (isQuoted(token.val) && token.val[0] !== '`') {

it goes inside the first if, but it's not "quoted", so doesn't go inside the second if
Now you have the token.val there and it contains the full string. It might be possible to pass this into e.g. a json or js parser as it is an array in your case.

Your example also has the following tokens:

[
    {"type":"tag","loc":{"start":{"line":1,"column":1},"end":{"line":1,"column":11}},"val":"MenuButton"},
    {"type":"start-attributes","loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":12}}},
    {"type":"attribute","loc":{"start":{"line":2,"column":3},"end":{"line":2,"column":123}},"name":"class","val":"[\"relative z-10 flex items-center w-11 gap-2 whitespace-nowrap text-ellipsis overflow-hidden text-xs\", \"lg:gap-6\"]","mustEscape":true},
    {"type":"end-attributes","loc":{"start":{"line":3,"column":1},"end":{"line":3,"column":2}}},
    {"type":"newline","loc":{"start":{"line":4,"column":1},"end":{"line":4,"column":1}}},
    {"type":"eos","loc":{"start":{"line":4,"column":1},"end":{"line":4,"column":1}}}
]

for this example:

MenuButton(
  class="relative",
  class=["relative z-10 flex items-center w-11 gap-2 whitespace-nowrap text-ellipsis overflow-hidden text-xs", "lg:gap-6"]
)

I just added another class attribute, just to show that the first is quoted and the second (your example) is not counted as quoted

That's all of the help I can give you for the start, now good luck :)

@vcharov
Copy link
Author

vcharov commented Sep 14, 2022

Thanks

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

No branches or pull requests

2 participants