Skip to content

Commit 9eefe73

Browse files
feat(obsidian): add button to disable rules from within popup (#2300)
1 parent e657944 commit 9eefe73

File tree

2 files changed

+122
-78
lines changed

2 files changed

+122
-78
lines changed

packages/obsidian-plugin/src/State.ts

Lines changed: 75 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -131,77 +131,88 @@ export default class State {
131131
const text = view.state.doc.sliceString(-1);
132132
const chars = Array.from(text);
133133

134-
const lints = await this.harper.lint(text);
134+
const lints = await this.harper.organizedLints(text);
135+
136+
return Object.entries(lints).flatMap(([linterName, lints]) =>
137+
lints.map((lint) => {
138+
const span = lint.span();
139+
140+
const actions = lint.suggestions().map((sug) => {
141+
return {
142+
name:
143+
sug.kind() == SuggestionKind.Replace
144+
? sug.get_replacement_text()
145+
: suggestionToLabel(sug),
146+
title: suggestionToLabel(sug),
147+
apply: (view) => {
148+
if (sug.kind() === SuggestionKind.Remove) {
149+
view.dispatch({
150+
changes: {
151+
from: span.start,
152+
to: span.end,
153+
insert: '',
154+
},
155+
});
156+
} else if (sug.kind() === SuggestionKind.Replace) {
157+
view.dispatch({
158+
changes: {
159+
from: span.start,
160+
to: span.end,
161+
insert: sug.get_replacement_text(),
162+
},
163+
});
164+
} else if (sug.kind() === SuggestionKind.InsertAfter) {
165+
view.dispatch({
166+
changes: {
167+
from: span.end,
168+
to: span.end,
169+
insert: sug.get_replacement_text(),
170+
},
171+
});
172+
}
173+
},
174+
};
175+
});
135176

136-
return lints.map((lint) => {
137-
const span = lint.span();
177+
if (lint.lint_kind() === 'Spelling') {
178+
const word = lint.get_problem_text();
179+
180+
actions.push({
181+
name: '📖',
182+
title: `Add “${word}” to your dictionary`,
183+
apply: (_view) => {
184+
this.harper.importWords([word]);
185+
this.reinitialize();
186+
},
187+
});
188+
}
138189

139-
const actions = lint.suggestions().map((sug) => {
140190
return {
141-
name:
142-
sug.kind() == SuggestionKind.Replace
143-
? sug.get_replacement_text()
144-
: suggestionToLabel(sug),
145-
title: suggestionToLabel(sug),
146-
apply: (view) => {
147-
if (sug.kind() === SuggestionKind.Remove) {
148-
view.dispatch({
149-
changes: {
150-
from: span.start,
151-
to: span.end,
152-
insert: '',
153-
},
154-
});
155-
} else if (sug.kind() === SuggestionKind.Replace) {
156-
view.dispatch({
157-
changes: {
158-
from: span.start,
159-
to: span.end,
160-
insert: sug.get_replacement_text(),
161-
},
162-
});
163-
} else if (sug.kind() === SuggestionKind.InsertAfter) {
164-
view.dispatch({
165-
changes: {
166-
from: span.end,
167-
to: span.end,
168-
insert: sug.get_replacement_text(),
169-
},
170-
});
171-
}
191+
from: span.start,
192+
to: span.end,
193+
source: linterName,
194+
severity: 'error',
195+
title: lint.lint_kind_pretty(),
196+
renderMessage: (_view) => {
197+
const node = document.createElement('template');
198+
node.innerHTML = lint.message_html();
199+
return node.content;
172200
},
173-
};
174-
});
175-
176-
if (lint.lint_kind() === 'Spelling') {
177-
const word = lint.get_problem_text();
201+
ignore: async () => {
202+
await this.ignoreLints(text, [lint]);
203+
},
204+
disable: async () => {
205+
const lintConfig = await this.harper.getLintConfig();
206+
lintConfig[linterName] = false;
207+
await this.harper.setLintConfig(lintConfig);
178208

179-
actions.push({
180-
name: '📖',
181-
title: `Add “${word}” to your dictionary`,
182-
apply: (_view) => {
183-
this.harper.importWords([word]);
184-
this.reinitialize();
209+
await this.reinitialize();
185210
},
186-
});
187-
}
188211

189-
return {
190-
from: span.start,
191-
to: span.end,
192-
severity: 'error',
193-
title: lint.lint_kind_pretty(),
194-
renderMessage: (_view) => {
195-
const node = document.createElement('template');
196-
node.innerHTML = lint.message_html();
197-
return node.content;
198-
},
199-
ignore: async () => {
200-
await this.ignoreLints(text, [lint]);
201-
},
202-
actions,
203-
};
204-
});
212+
actions,
213+
};
214+
}),
215+
);
205216
},
206217
{
207218
delay: this.delay,

packages/obsidian-plugin/src/lint.ts

Lines changed: 47 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export interface Diagnostic {
5252
actions?: readonly Action[];
5353
/// A callback for when the user selects to "ignore" the diagnostic.
5454
ignore?: () => void;
55+
/// A callback for when the user selects to "disable" the source of the diagnostic.
56+
disable?: () => void;
5557
}
5658

5759
/// An action associated with a diagnostic.
@@ -428,21 +430,37 @@ function renderDiagnostic(view: EditorView, diagnostic: Diagnostic, inPanel: boo
428430
);
429431
}),
430432
),
431-
diagnostic.ignore &&
432-
elt(
433-
'div',
434-
{
435-
class: 'cm-diagnosticIgnore',
436-
onclick: (e) => {
437-
e.preventDefault();
438-
if (diagnostic.ignore) {
439-
diagnostic.ignore();
440-
}
433+
elt('div', { class: 'cm-diagnosticRow' }, [
434+
diagnostic.ignore &&
435+
elt(
436+
'div',
437+
{
438+
class: 'cm-diagnosticIgnore',
439+
onclick: (e) => {
440+
e.preventDefault();
441+
if (diagnostic.ignore) {
442+
diagnostic.ignore();
443+
}
444+
},
441445
},
442-
},
443-
'Ignore Diagnostic',
444-
),
445-
diagnostic.source && elt('div', { class: 'cm-diagnosticSource' }, diagnostic.source),
446+
'Ignore Diagnostic',
447+
),
448+
diagnostic.disable &&
449+
elt(
450+
'div',
451+
{
452+
class: 'cm-diagnosticDisable',
453+
onclick: (e) => {
454+
e.preventDefault();
455+
if (diagnostic.disable) {
456+
diagnostic.disable();
457+
}
458+
},
459+
title: `Disable ${diagnostic.source}`,
460+
},
461+
'Disable Rule',
462+
),
463+
]),
446464
);
447465
}
448466

@@ -514,6 +532,12 @@ const baseTheme = EditorView.baseTheme({
514532
gap: 'var(--size-4-2)',
515533
},
516534

535+
'.cm-diagnosticRow': {
536+
display: 'flex',
537+
flexDirection: 'row',
538+
justifyContent: 'space-between',
539+
},
540+
517541
'.cm-diagnosticAction': {
518542
font: 'inherit',
519543
border: 'none',
@@ -553,6 +577,15 @@ const baseTheme = EditorView.baseTheme({
553577
textDecoration: 'underline',
554578
},
555579

580+
'.cm-diagnosticDisable': {
581+
padding: 'var(--size-4-1) 0px',
582+
fontSize: 'var(--font-ui-small)',
583+
},
584+
585+
'.cm-diagnosticDisable:hover': {
586+
textDecoration: 'underline',
587+
},
588+
556589
'.cm-lintRange': {
557590
backgroundPosition: 'left bottom',
558591
backgroundRepeat: 'repeat-x',

0 commit comments

Comments
 (0)