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 Folder Lint Option to Right Click Folder Action Menu #199

Merged
merged 5 commits into from
May 13, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ Rules can be toggled and configured in the settings.
## Usage

To lint the current file, run `Lint the current file` (`Ctrl+Alt+L` by default).
To lint the all files, run `Lint all files in the vault`.
To lint all files, run `Lint all files in the vault`.
To lint all files in the current folder run `Lint all files in the current folder`. This action includes all subfolders.
You can also lint a folder by right clicking on it in the folder list and selecting "Lint folder" from the options.

![Lint folder contents](images/lintfolder.png)

When `Lint on save` is toggled on, the plugin will lint the current file on manual save (when you press `Ctrl+S`).

Expand Down Expand Up @@ -77,14 +81,15 @@ Documentation for all rules can be found in the [rules docs](https://github.com/

Pull requests are welcome, especially for new rules.

1. Clone the repository
2. Run `npm ci` to install dependencies
3. Add a new rule in `rules.ts`.
1. Fork this repository
2. Clone the repository
3. Run `npm ci` to install dependencies
4. Add a new rule in `rules.ts`.
1. Insert a new rule in the corresponding rule type(spacing, headings, etc)
2. Follow the format of the existing rules
3. Add tests for edge cases in `test.ts`
4. You should probably use some helper functions from `utils.ts`, such as `ignoreCodeBlocksAndYAML`.
4. Run `npm run compile` to build, generate documentation, and test the plugin.
5. Run `npm run lint` to lint the plugin.
5. Run `npm run compile` to build, generate documentation, and test the plugin.
6. Run `npm run lint` to lint the plugin.

Make sure to use Node 15.x or higher.
17 changes: 11 additions & 6 deletions docs/readme_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ Rules can be toggled and configured in the settings.
## Usage

To lint the current file, run `Lint the current file` (`Ctrl+Alt+L` by default).
To lint the all files, run `Lint all files in the vault`.
To lint all files, run `Lint all files in the vault`.
To lint all files in the current folder run `Lint all files in the current folder`. This action includes all subfolders.
You can also lint a folder by right clicking on it in the folder list and selecting "Lint folder" from the options.

![Lint folder contents](images/lintfolder.png)

When `Lint on save` is toggled on, the plugin will lint the current file on manual save (when you press `Ctrl+S`).

Expand Down Expand Up @@ -36,14 +40,15 @@ Documentation for all rules can be found in the [rules docs](https://github.com/

Pull requests are welcome, especially for new rules.

1. Clone the repository
2. Run `npm ci` to install dependencies
3. Add a new rule in `rules.ts`.
1. Fork this repository
2. Clone the repository
3. Run `npm ci` to install dependencies
4. Add a new rule in `rules.ts`.
1. Insert a new rule in the corresponding rule type(spacing, headings, etc)
2. Follow the format of the existing rules
3. Add tests for edge cases in `test.ts`
4. You should probably use some helper functions from `utils.ts`, such as `ignoreCodeBlocksAndYAML`.
4. Run `npm run compile` to build, generate documentation, and test the plugin.
5. Run `npm run lint` to lint the plugin.
5. Run `npm run compile` to build, generate documentation, and test the plugin.
6. Run `npm run lint` to lint the plugin.

Make sure to use Node 15.x or higher.
Binary file added images/lintfolder.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 61 additions & 8 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {App, Editor, EventRef, MarkdownView, Menu, Modal, Notice, Plugin, PluginSettingTab, Setting, TAbstractFile, TFile} from 'obsidian';
import {App, Editor, EventRef, MarkdownView, Menu, Modal, Notice, Plugin, PluginSettingTab, Setting, TAbstractFile, TFile, TFolder} from 'obsidian';
import {LinterSettings, Options, rules, getDisabledRules} from './rules';
import DiffMatchPatch from 'diff-match-patch';
import moment from 'moment';
Expand Down Expand Up @@ -30,10 +30,36 @@ export default class LinterPlugin extends Plugin {
id: 'lint-all-files',
name: 'Lint all files in the vault',
callback: () => {
new ConfirmationModal(this.app, this).open();
const startMessage = 'This will edit all of your files and may introduce errors.';
const submitBtnText = 'Lint All';
const submitBtnNoticeText = 'Linting all files...';
new LintConfirmationModal(this.app, startMessage, submitBtnText, submitBtnNoticeText, this.runLinterAllFiles).open();
},
});

this.addCommand({
id: 'lint-all-files-in-folder',
name: 'Lint all files in the current folder',
editorCallback: (_) => {
this.createFolderLintModal(this.app.workspace.getActiveFile().parent);
},
});

// https://github.com/mgmeyers/obsidian-kanban/blob/main/src/main.ts#L239-L251
this.registerEvent(
this.app.workspace.on('file-menu', (menu, file: TFile) => {
// Add a menu item to the folder context menu to create a board
if (file instanceof TFolder) {
menu.addItem((item) => {
item
.setTitle('Lint folder')
.setIcon('wrench-screwdriver-glyph')
.onClick(() => this.createFolderLintModal(file));
});
}
}),
);

this.eventRef = this.app.workspace.on('file-menu',
(menu, file, source) => this.onMenuOpenCallback(menu, file, source));
this.registerEvent(this.eventRef);
Expand Down Expand Up @@ -180,6 +206,32 @@ export default class LinterPlugin extends Plugin {
new Notice('Linted all files');
}

async runLinterAllFilesInFolder(folder: TFolder) {
console.log('Linting folder ' + folder.name);

let lintedFiles = 0;
await Promise.all(this.app.vault.getMarkdownFiles().map(async (file) => {
if (this.convertPathToNormalizedString(file.path).startsWith(this.convertPathToNormalizedString(folder.path) + '|') && !this.shouldIgnoreFile(file)) {
await this.runLinterFile(file);
lintedFiles++;
}
}));
new Notice('Linted all ' + lintedFiles + ' files in ' + folder.name);
}

// convert the path separators to | in order to "normalize" the path for better comparisons
convertPathToNormalizedString(path: string): string {
return path.replace('\\', '|').replace('/', '|');
}

// handles the creation of the folder linting modal since this happens in multiple places and it should be consistent
createFolderLintModal(folder: TFolder) {
const startMessage = 'This will edit all of your files in ' + folder.name + ' including files in its subfolders which may introduce errors.';
const submitBtnText = 'Lint All Files in ' + folder.name;
const submitBtnNoticeText = 'Linting all files in ' + folder.name + '...';
new LintConfirmationModal(this.app, startMessage, submitBtnText, submitBtnNoticeText, () => this.runLinterAllFilesInFolder(folder)).open();
}

runLinterEditor(editor: Editor) {
console.log('running linter');

Expand Down Expand Up @@ -375,15 +427,16 @@ class SettingTab extends PluginSettingTab {
}

// https://github.com/nothingislost/obsidian-workspaces-plus/blob/bbba928ec64b30b8dec7fe8fc9e5d2d96543f1f3/src/modal.ts#L68
class ConfirmationModal extends Modal {
constructor(app: App, plugin: LinterPlugin) {
class LintConfirmationModal extends Modal {
constructor(app: App, startModalMessageText: string, submitBtnText: string,
submitBtnNoticeText: string, btnSubmitAction: () => Promise<void>) {
super(app);
this.modalEl.addClass('confirm-modal');

this.contentEl.createEl('h3', {text: 'Warning'});

const e: HTMLParagraphElement = this.contentEl.createEl('p',
{text: 'This will edit all of your files and may introduce errors. Make sure you have backed up your files.'});
{text: startModalMessageText + ' Make sure you have backed up your files.'});
e.id = 'confirm-dialog';

this.contentEl.createDiv('modal-button-container', (buttonsEl) => {
Expand All @@ -392,12 +445,12 @@ class ConfirmationModal extends Modal {
const btnSumbit = buttonsEl.createEl('button', {
attr: {type: 'submit'},
cls: 'mod-cta',
text: 'Lint All',
text: submitBtnText,
});
btnSumbit.addEventListener('click', async (e) => {
new Notice('Linting all files...');
new Notice(submitBtnNoticeText);
this.close();
await plugin.runLinterAllFiles();
await btnSubmitAction();
});
setTimeout(() => {
btnSumbit.focus();
Expand Down