Repository: platers/obsidian-linter (ts)

Issue:
FR: Rule to add newline after front matter
## Is Your Feature Request Related to a Problem? Please Describe.

For now we have option "Empty Line Between YAML and Header", but would be nice to have something like "Empty Line After YAML" which adds empty line after front matter and next node (header, paragraph, list etc), because not every note has header right after front matter.

## Describe the Solution You'd Like

Add option `Empty Line After YAML` to automatically insert new line after YAML front matter.

**Please include an example where applicable:**

``` markdown
---
tags: foo, bar
---
Hello, world!
```

``` markdown
---
tags: foo, bar
---

Hello, world!
```

## Describe Alternatives You've Considered

-

## Additional Context

-


Pull request:
Add Rule `Add Blank Line After YAML`
Fixes #873 

Changes Made:
- Added a rule that adds a blank line after frontmatter if there is not at least 1 empty line after it and it has content after it.
- Added tests for a couple of edge cases
- Added some examples for how it works
- Added wording for the settings UI for English

Patch:
diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts
index d507203..678729a 100644
--- a/src/lang/locale/en.ts
+++ b/src/lang/locale/en.ts
@@ -233,6 +233,11 @@ export default {
         'description': 'A comma separated list of lowercased words to ignore when auto-correcting',
       },
     },
+    // add-blank-line-after-yaml.ts
+    'add-blank-line-after-yaml': {
+      'name': 'Add Blank Line After YAML',
+      'description': 'Adds a blank line after the YAML block if it does not end the current file or it is not already followed by at least 1 blank line',
+    },
     // blockquotify-on-paste.ts
     'add-blockquote-indentation-on-paste': {
       'name': 'Add Blockquote Indentation on Paste',
diff --git a/src/rules/add-blank-line-after-yaml.ts b/src/rules/add-blank-line-after-yaml.ts
new file mode 100644
index 0000000..61cfa21
--- /dev/null
+++ b/src/rules/add-blank-line-after-yaml.ts
@@ -0,0 +1,91 @@
+import {Options, RuleType} from '../rules';
+import RuleBuilder, {ExampleBuilder, OptionBuilderBase} from './rule-builder';
+import dedent from 'ts-dedent';
+import {yamlRegex} from '../utils/regex';
+
+class AddBlankLineAfterYAMLOptions implements Options {
+}
+
+@RuleBuilder.register
+export default class AddBlankLineAfterYAML extends RuleBuilder<AddBlankLineAfterYAMLOptions> {
+  constructor() {
+    super({
+      nameKey: 'rules.add-blank-line-after-yaml.name',
+      descriptionKey: 'rules.add-blank-line-after-yaml.description',
+      type: RuleType.YAML,
+    });
+  }
+  get OptionsClass(): new () => AddBlankLineAfterYAMLOptions {
+    return AddBlankLineAfterYAMLOptions;
+  }
+  apply(text: string, options: AddBlankLineAfterYAMLOptions): string {
+    const yaml = text.match(yamlRegex);
+    if (yaml === null) {
+      return text;
+    }
+
+    const yamlText = yaml[0];
+
+    const endOfYamlIndex = text.indexOf(yamlText) + yamlText.length;
+
+    // there is nothing to add if the YAML ends the content in the file or the character after the YAML is a new line character
+    if (endOfYamlIndex+1 >= text.length || text.trimEnd() === yamlText.trimEnd() || text.charAt(endOfYamlIndex+1) === '\n') {
+      return text;
+    }
+
+    return text.replace(yamlText, yamlText + '\n');
+  }
+  get exampleBuilders(): ExampleBuilder<AddBlankLineAfterYAMLOptions>[] {
+    return [
+      new ExampleBuilder({
+        description: 'A file with just YAML in it does not get a blank line after the YAML',
+        before: dedent`
+          ---
+          key: value
+          ---
+        `,
+        after: dedent`
+          ---
+          key: value
+          ---
+        `,
+      }),
+      new ExampleBuilder({
+        description: 'A file with YAML followed directly by content has an empty line added',
+        before: dedent`
+          ---
+          key: value
+          ---
+          Here is some text
+        `,
+        after: dedent`
+          ---
+          key: value
+          ---
+          ${''}
+          Here is some text
+        `,
+      }),
+      new ExampleBuilder({
+        description: 'A file with YAML that already has a blank line after it and before content has no empty line added',
+        before: dedent`
+          ---
+          key: value
+          ---
+          ${''}
+          Here is some text
+        `,
+        after: dedent`
+          ---
+          key: value
+          ---
+          ${''}
+          Here is some text
+        `,
+      }),
+    ];
+  }
+  get optionBuilders(): OptionBuilderBase<AddBlankLineAfterYAMLOptions>[] {
+    return [];
+  }
+}


Test patch:
diff --git a/__tests__/add-blank-line-after-yaml.test.ts b/__tests__/add-blank-line-after-yaml.test.ts
new file mode 100644
index 0000000..47c533a
--- /dev/null
+++ b/__tests__/add-blank-line-after-yaml.test.ts
@@ -0,0 +1,54 @@
+import AddBlankLineAfterYAML from '../src/rules/add-blank-line-after-yaml';
+import dedent from 'ts-dedent';
+import {ruleTest} from './common';
+
+ruleTest({
+  RuleBuilderClass: AddBlankLineAfterYAML,
+  testCases: [
+    {
+      testName: 'Make sure that no YAML means no change to the text',
+      before: dedent`
+        Here is some text.
+      `,
+      after: dedent`
+        Here is some text.
+      `,
+    },
+    {
+      testName: 'If there are multiple blank lines after a YAML block, they are left alone',
+      before: dedent`
+        ---
+        key: value
+        ---
+        ${''}
+        ${''}
+        Content here.
+      `,
+      after: dedent`
+        ---
+        key: value
+        ---
+        ${''}
+        ${''}
+        Content here.
+      `,
+    },
+    {
+      testName: 'If there are multiple blank lines after a YAML block and they end the file content, they should be left alone',
+      before: dedent`
+        ---
+        key: value
+        ---
+        ${''}
+        ${''}
+      `,
+      after: dedent`
+        ---
+        key: value
+        ---
+        ${''}
+        ${''}
+      `,
+    },
+  ],
+});