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

Feature Reuqest: Ability to convert Quoted Scalar values to Block Folded Scalar values with Chomping #212

Open
klondikemarlen opened this issue Feb 8, 2023 · 6 comments
Labels
enhancement New feature or request needs bikeshedding Minor details about this change need to be discussed

Comments

@klondikemarlen
Copy link

I'd love this for Rails translation files.

e.g.

something: "%{some_key}"

to

something: >-
  %{some_key}

As parsed in

https://ota-meshi.github.io/yaml-eslint-parser/ results
{
  "type": "Program",
  "body": [
    {
      "type": "YAMLDocument",
      "directives": [
      ],
      "content": {
        "type": "YAMLMapping",
        "style": "block",
        "pairs": [
          {
            "type": "YAMLPair",
            "key": {
              "type": "YAMLScalar",
              "style": "plain",
              "strValue": "something",
              "value": "something",
              "raw": "something"
            },
            "value": {
              "type": "YAMLScalar",
              "style": "double-quoted",
              "strValue": "%{some_key}",
              "value": "%{some_key}",
              "raw": "\"%{some_key}\""
            }
          },
          {
            "type": "YAMLPair",
            "key": {
              "type": "YAMLScalar",
              "style": "plain",
              "strValue": "something2",
              "value": "something2",
              "raw": "something2"
            },
            "value": {
              "type": "YAMLScalar",
              "style": "folded",
              "chomping": "strip",
              "indent": null,
              "value": "%{some_key}"
            }
          }
        ]
      },
      "anchors": {
      },
      "version": "1.2"
    }
  ],
  "comments": [
  ],
  "sourceType": "module",
  "tokens": [
    {
      "type": "Identifier",
      "value": "something"
    },
    {
      "type": "Punctuator",
      "value": ":"
    },
    {
      "type": "String",
      "value": "\"%{some_key}\""
    },
    {
      "type": "Identifier",
      "value": "something2"
    },
    {
      "type": "Punctuator",
      "value": ":"
    },
    {
      "type": "Punctuator",
      "value": ">-"
    },
    {
      "type": "BlockFolded",
      "value": "%{some_key}"
    }
  ]
}
@ota-meshi
Copy link
Owner

Thank you for posting the issue.
But I don't know if it makes sense. Also I don't use Rails.
Could you please explain to me the details of the rules and why they are reasonable?

@ota-meshi ota-meshi added the needs more info More info is needed to complete the issue label Feb 8, 2023
@klondikemarlen
Copy link
Author

klondikemarlen commented Feb 9, 2023

Apologies, I don't know if this is actually reasonable. This would certainly make life easier for Rails developers working with translations in French and English, but please forgive me if this is outside the scope of this project.

At the company I work at, we have a Rails app with many I18n/translation files written in YAML. This is a standard pattern for Rails. Depending on the different locales you need to support, some languages have lots of single quotes or accents. In our case, we need to support both French, which has many accents, and single quotes, and English which uses a lot of single quotes.

We have the additional problem that Rails supports passing parameters to translations. This is a pretty standard pattern in the JS translation world too, I think? These translations are of the form some_key: "some %{value} other

We would like to avoid quoting the "keys" in the YAML as this makes the YAML quite hard to read.
We would also like to either quote all of the values, or quote none of the values, for consistency and readability, and to make the job of our translators easier.

This would be good.

some_key: "Some Translation"
some_key2: "Translation with ' in it"
some_key3: "%{argument} some translation with arguments"

or

some_key: Some Translation
some_key2: >-
  Translation with ' in it
some_key3: >-
  %{argument} some translation with arguments

We have thousand of lines of YAML like this in our app, and very deeply nested a well.

We are attempting to add linting via this wonderful ESLint plugin. However, there doesn't seem to be an option to support forcing quotes on "values", without also forcing quotes on "keys".

e.g. we end up with either

"some_key": "Some Translation"
"some_key2": "Translation with ' in it"
"some_key3": "%{argument} some translation with arguments"

or

some_key: Some Translation
some_key2: "Translation with ' in it"
some_key3: "%{argument} some translation with arguments"

So again, I'm not sure that this feature is reasonable, only that it would make it much easier to read and write translations files in YAML in French and English, and have beautiful consistency in the YAML format.

@ota-meshi
Copy link
Owner

Thanks for explaining it to me.
I think I understood your explanation. The additional examples you provided helped me understand the benefits of the rule.

To implement the rule, we first need to consider the use of what text should be converted to a folded style scalar or not.

I think the following example you provided should favor a plain scalar.

some_key: "Some Translation" # Bad
some_key: Some Translation # Good

 # Little better?
some_key: >-
  Some Translation

In addition, I think that the following confusing folded style scalars in non-translation-related text examples may be easier to read with quotes.

foo: "[1, 2, 3]" # Bad?

# But it is confusing.
foo: >-
  [1, 2, 3]

# If you want to write YAML within YAML, literal block scalars may be easier to read.
yaml: |
  - 1
  - 2
  - 3

@ota-meshi ota-meshi added enhancement New feature or request needs bikeshedding Minor details about this change need to be discussed and removed needs more info More info is needed to complete the issue labels Feb 9, 2023
@klondikemarlen
Copy link
Author

klondikemarlen commented Feb 9, 2023

I would say that, if possible, the minimum rule that would catch most of the needed cases for translations, would be a rule that only acted on text containing either a ' or a %{...} construct. Or had an option to specify the cases it could act on?

some_key: "Some Translation" # Bad
some_key: Some Translation # Good

some_key: "Some Translation with ' single quote" # Bad
some_key: >-
  Some Translation with ' single quote # Good

some_key: "Some Translation with %{variable} interpolation" # Bad
some_key: >-
  Some Translation with %{variable} interpolation # Good

This rule would need to be non-default, since it would make the YAML in YAML case much harder to read. If I'm understanding the ESLint config correctly it could also be implemented only in a specific set of sub-directories?

module.exports = {
  extends: ["plugin:yml/standard"],
  overrides: [
    {
      files: ["some/translation/directory/**/*.yaml", "some/translation/directory/**/*.yml"],
      parser: "yaml-eslint-parser",
      rules: { // Example of new rule
        "yml/prefer-chomped-block-folding-over-quoting": ["error", "always"]
      }
    },
  ],
};

@klondikemarlen
Copy link
Author

For the simplest use case, I ended up transforming everything that eslint-plugin-yml double quoted for me, in a given directory via:

function block_fold_quoted_yaml(filePath) {
  file = fs.readFileSync(filePath, 'utf8');

  doc = YAML.parseDocument(file, {
    keepSourceTokens: true,
  });

  YAML.visit(doc, {
    Scalar(key, node) {
      if (
        key !== 'key' &&
        typeof node.value === 'string' &&
        node.type === 'QUOTE_DOUBLE'
      ) {
        node.type = 'BLOCK_FOLDED';
      }
    },
  });

  string = doc.toString();

  file = fs.writeFileSync(filePath, string, 'utf8');
}

const YAML = require('yaml');
const fs = require('fs');

block_fold_quoted_yaml('some/path/')

Even if the feature never gets implement, I hope this will help someone else.

@ota-meshi
Copy link
Owner

ota-meshi commented Feb 10, 2023

I think it would be good to have a rule that allows defining the preferred string style for each string value.
But I don't yet have an idea of what options a rule accepts that would be of value to the user 😓.

"yml/string-value-style": ["error",
  {
    "prefer": "folded",
    "matchValues": ["'", "/%\\{.*?\\}/u"]
    // ... We may need more ideas.
  }, 
  {
    "prefer": "quoted",
    "matchValues": ["/^[/u"]
    // ... 
  },
  {
    "prefer": "literal",
    "matchKeys": ["/^YAML$/ui"]
    // ...
  },
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request needs bikeshedding Minor details about this change need to be discussed
Projects
None yet
Development

No branches or pull requests

2 participants