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

Add rule YAML Title Alias #256

Merged
merged 21 commits into from
Jul 7, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Documentation for all rules can be found in the [rules docs](https://github.com/
- [insert-yaml-attributes](https://github.com/platers/obsidian-linter/blob/master/docs/rules.md#insert-yaml-attributes)
- [yaml-timestamp](https://github.com/platers/obsidian-linter/blob/master/docs/rules.md#yaml-timestamp)
- [yaml-title](https://github.com/platers/obsidian-linter/blob/master/docs/rules.md#yaml-title)
- [yaml-title-alias](https://github.com/platers/obsidian-linter/blob/master/docs/rules.md#yaml-title-alias)
- [escape-yaml-special-characters](https://github.com/platers/obsidian-linter/blob/master/docs/rules.md#escape-yaml-special-characters)

### Heading rules
Expand Down
52 changes: 52 additions & 0 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,58 @@ title: Filename

```

### YAML Title Alias

Alias: `yaml-title-alias`

Inserts the title of the file into the YAML frontmatter's aliases section. Gets the title from the first H1 or filename.

Options:
- YAML aliases new section style: The style of the newly created aliases YAML property
- Default: `Multi-line array`
- `Multi-line array`: ```aliases:\n - Title```
- `Single-line array`: ```aliases: [Title]```
- `Single string`: ```aliases: Title```
- YAML aliases new array style: The style of the aliases YAML property for newly created arrays
- Default: `Multi-line array`
- `Multi-line array`: ```aliases:\n - Title```
- `Single-line array`: ```aliases: [Title]```

Example: Adds a header with the title from heading.

Before:

```markdown
# Obsidian
```

After:

```markdown
---
aliases:
- Obsidian # linter-yaml-title-alias
---
# Obsidian
```
Example: Adds a header with the title.

Before:

```markdown

```

After:

```markdown
---
aliases:
- Filename # linter-yaml-title-alias
---

```

### Escape YAML Special Characters

Alias: `escape-yaml-special-characters`
Expand Down
167 changes: 165 additions & 2 deletions src/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import {
loadYAML,
moveFootnotesToEnd,
yamlRegex,
escapeYamlString,
toYamlString,
makeEmphasisOrBoldConsistent,
addTwoSpacesAtEndOfLinesFollowedByAnotherLineOfTextContent,
makeSureThereIsOnlyOneBlankLineBeforeAndAfterParagraphs,
removeSpacesInLinkText,
toSingleLineArrayYamlString,
} from './utils';
import {
Option,
Expand Down Expand Up @@ -1606,7 +1607,7 @@ export const rules: Rule[] = [
});
title = title || options['metadata: file name'];

title = escapeYamlString(title);
title = toYamlString(title);

return formatYAML(text, (text) => {
const title_match_str = `\n${options['Title Key']}.*\n`;
Expand Down Expand Up @@ -1658,6 +1659,168 @@ export const rules: Rule[] = [
[new TextOption('Title Key', 'Which YAML key to use for title', 'title')],
),

new Rule(
'YAML Title Alias',
'Inserts the title of the file into the YAML frontmatter\'s aliases section. Gets the title from the first H1 or filename.',
RuleType.YAML,
(text: string, options = {}) => {
text = initYAML(text);
let title = ignoreCodeBlocksYAMLTagsAndLinks(text, (text) => {
const result = text.match(/^#\s+(.*)/m);
if (result) {
return result[1];
}
return '';
});
title = title || options['metadata: file name'];

let yaml = text.match(yamlRegex)[1];
const aliasesRegex = /(?<=^|\n)aliases:[ \t]*(\S.*|(?:\n {2}\S.*)+)\n(?=$|\S)/;
let aliasesMatch = yaml.match(aliasesRegex);

const linterMarkerComment = '# linter-yaml-title-alias';

if (!aliasesMatch) {
let emptyValue;
switch (options['YAML aliases new section style']) {
case 'Multi-line array':
emptyValue = '\n - \'\'';
break;
case 'Single-line array':
emptyValue = ' [\'\']';
break;
case 'Single string':
emptyValue = ' \'\'';
break;
default:
throw new Error(`Unsupported setting 'YAML aliases new section style': ${options['YAML aliases new section style']}`);
}

const newAliasesSection = `aliases:${emptyValue} ${linterMarkerComment}\n`;
pjkaufman marked this conversation as resolved.
Show resolved Hide resolved
let newYaml = yaml.replace(/(?<=^|\n)aliases:\s*/, newAliasesSection);

if (newYaml === yaml) {
newYaml = `${newAliasesSection}${yaml}`;
}
pjkaufman marked this conversation as resolved.
Show resolved Hide resolved

text = text.replace(`---\n${yaml}---`, `---\n${newYaml}---`);
yaml = newYaml;
aliasesMatch = yaml.match(aliasesRegex);
}

const aliasesValue = aliasesMatch[1];

const hasLinterMarkerComment = aliasesValue.includes(linterMarkerComment);

const isMultiline = aliasesValue.includes('\n');
const parsedAliases = loadYAML(aliasesValue);

const isSingleString = !isMultiline && aliasesValue.match(/^\[.*\]/) === null;

let resultAliasesArray = isSingleString ? [parsedAliases] : [...parsedAliases];

if (hasLinterMarkerComment) {
resultAliasesArray[0] = title;
} else {
resultAliasesArray = [title, ...resultAliasesArray];
}

const resultStyle = isSingleString ? (hasLinterMarkerComment ? 'Single string' : options['YAML aliases new array style']) : (isMultiline ? 'Multi-line array' : 'Single-line array');

let newAliasesYaml;

switch (resultStyle) {
case 'Multi-line array': {
const tailArrayYaml = resultAliasesArray.length === 1 ? '' : `\n${toYamlString(resultAliasesArray.slice(1))}`.replace(/\n-/g, '\n -');
newAliasesYaml = `\n - ${toYamlString(resultAliasesArray[0])} ${linterMarkerComment}${tailArrayYaml}`;
break;
}
case 'Single-line array':
newAliasesYaml = ` ${toSingleLineArrayYamlString(resultAliasesArray)} ${linterMarkerComment}`;
break;
case 'Single string':
newAliasesYaml = ` ${toYamlString(resultAliasesArray[0])} ${linterMarkerComment}`;
break;
default:
throw new Error(`Unsupported resultStyle: ${resultStyle}`);
}

text = text.replace(aliasesMatch[0], `aliases:${newAliasesYaml}\n`);

return text;
},
[
new Example(
'Adds a header with the title from heading.',
dedent`
# Obsidian
`,
dedent`
---
aliases:
- Obsidian # linter-yaml-title-alias
---
# Obsidian
`,
{
'YAML aliases new section style': 'Multi-line array',
},
),
new Example(
'Adds a header with the title.',
dedent`
`,
dedent`
---
aliases:
- Filename # linter-yaml-title-alias
---

`,
{
'metadata: file name': 'Filename',
'YAML aliases new section style': 'Multi-line array',
},
),
],
[
new DropdownOption(
'YAML aliases new section style',
'The style of the newly created aliases YAML property',
'Multi-line array',
[
new DropdownRecord(
'Multi-line array',
'```aliases:\\n - Title```',
),
new DropdownRecord(
'Single-line array',
'```aliases: [Title]```',
),
new DropdownRecord(
'Single string',
'```aliases: Title```',
),
],
),
new DropdownOption(
'YAML aliases new array style',
'The style of the aliases YAML property for newly created arrays',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a smaller thing, but could we by chance make it clear that this only applies when going from a single-line string to an array when multiple values are present?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am considering to merge two dropdowns into one and making four options

  • Multi-line array
  • Single-line array
  • Single string, that extends to multi-line array if needed
  • Single string, that extends to single-line array if needed

'Multi-line array',
[
new DropdownRecord(
'Multi-line array',
'```aliases:\\n - Title```',
),
pjkaufman marked this conversation as resolved.
Show resolved Hide resolved
new DropdownRecord(
'Single-line array',
'```aliases: [Title]```',
),
],
),
],
),

new Rule(
'Escape YAML Special Characters',
'Escapes colons with a space after them (: ), single quotes (\'), and double quotes (") in YAML.',
Expand Down
Loading