mirror of
https://github.com/adamfletcher/obsidian-cut-the-fluff.git
synced 2026-07-22 05:46:18 +00:00
Refactor to support partial highlighting of matches
This commit is contained in:
parent
d284b0aa0d
commit
c852a68ecb
2 changed files with 208 additions and 192 deletions
160
main.ts
160
main.ts
|
|
@ -10,7 +10,7 @@ import {
|
|||
import { RangeSetBuilder } from '@codemirror/state';
|
||||
import { syntaxTree } from '@codemirror/language';
|
||||
|
||||
import { Rulesets, RULESETS } from './rulesets';
|
||||
import { Rules, Rule, RuleType } from './rulesets';
|
||||
|
||||
|
||||
interface CutTheFluffPluginSettings {
|
||||
|
|
@ -41,12 +41,17 @@ const DEFAULT_SETTINGS: CutTheFluffPluginSettings = {
|
|||
export default class CutTheFluffPlugin extends Plugin {
|
||||
settings: CutTheFluffPluginSettings;
|
||||
forceViewUpdate: boolean;
|
||||
regex: RegExp;
|
||||
regex: RegExp | null;
|
||||
rules: Rules;
|
||||
|
||||
async onload() {
|
||||
|
||||
this.rules = new Rules();
|
||||
|
||||
await this.loadSettings();
|
||||
this.buildRegex();
|
||||
|
||||
|
||||
this.addCommand({
|
||||
id: 'toggle',
|
||||
name: 'Toggle highlighting',
|
||||
|
|
@ -66,78 +71,38 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
}
|
||||
|
||||
buildRegex() {
|
||||
/*const words = [
|
||||
'basically',
|
||||
'just',
|
||||
'basically',
|
||||
'actually',
|
||||
'actual',
|
||||
'literally',
|
||||
'really',
|
||||
'very',
|
||||
'quite',
|
||||
'honestly',
|
||||
'simply',
|
||||
'like',
|
||||
'combine together'
|
||||
];*/
|
||||
|
||||
const customRules: string[] = [];
|
||||
|
||||
const enabledRuleTypes: RuleType[] = [
|
||||
...(this.settings.enableRulesetWeakQualifiers ? [RuleType.WeakQualifier] : []),
|
||||
...(this.settings.enableRulesetJargon ? [RuleType.Jargon] : []),
|
||||
...(this.settings.enableRulesetComplexity ? [RuleType.Complexity] : []),
|
||||
...(this.settings.enableRulesetRedudancies ? [RuleType.Redundancy] : []),
|
||||
];
|
||||
|
||||
this.rules.resetCustomRules();
|
||||
const customExceptions: string[] = [];
|
||||
|
||||
|
||||
|
||||
this.settings.customWordList.trim().split(/\r?\n/).forEach(str => {
|
||||
if (str.startsWith('-')) {
|
||||
customExceptions.push(str.substring(1));
|
||||
} else {
|
||||
customRules.push(str);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//const filteredArray = stringArray.filter(str => str.startsWith('-'));
|
||||
|
||||
let words: string[] = [];
|
||||
|
||||
const rulesetSettingMap: Record<string, string> = {
|
||||
"enableRulesetWeakQualifiers": 'weakQualifiers',
|
||||
"enableRulesetJargon": 'jargon',
|
||||
"enableRulesetComplexity": 'complexity',
|
||||
"enableRulesetRedudancies": 'redundancies'
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (let key in rulesetSettingMap) {
|
||||
let rulesetToggleSettingKey = key as keyof CutTheFluffPluginSettings;
|
||||
if (typeof this.settings[rulesetToggleSettingKey] === 'boolean') {
|
||||
if (this.settings[rulesetToggleSettingKey]) {
|
||||
let typedKey = rulesetSettingMap[key] as keyof Rulesets;
|
||||
|
||||
words = words.concat(Object.keys(RULESETS[typedKey]).filter(value => {
|
||||
return !customExceptions.includes(value);
|
||||
}));
|
||||
if(this.settings.customWordList.trim().length > 0) {
|
||||
this.settings.customWordList.trim().split(/\r?\n/).forEach(str => {
|
||||
if (str.startsWith('-')) {
|
||||
customExceptions.push(str.substring(1));
|
||||
} else {
|
||||
this.rules.addCustomRule(str);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
if(this.settings.customWordList.length > 0) {
|
||||
words = words.concat(customRules.map(
|
||||
line => line.trim().replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
||||
));
|
||||
let words: string[] = this.rules.getMatchStrings(enabledRuleTypes, customExceptions);
|
||||
|
||||
if(words.length > 0) {
|
||||
const pattern = `\\b(?:${words.join("|")})\\b`
|
||||
this.regex = new RegExp(pattern, 'gi');
|
||||
} else {
|
||||
this.regex = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//const words = this.settings.wordlist.trim().split(/\r?\n/).map(line => line.trim());
|
||||
|
||||
const pattern = `\\b(?:${words.join("|")})\\b`
|
||||
this.regex = new RegExp(pattern, 'gi');
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
|
|
@ -148,7 +113,7 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
await this.saveData(this.settings);
|
||||
this.buildRegex();
|
||||
this.forceViewUpdate = true;
|
||||
document.body.classList.toggle('sentence-length-highlighting-active', this.settings.enabled);
|
||||
document.body.classList.toggle('cut-the-fluff-active', this.settings.enabled);
|
||||
this.app.workspace.updateOptions();
|
||||
}
|
||||
|
||||
|
|
@ -165,12 +130,13 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
update(update: ViewUpdate) {
|
||||
if (update.docChanged || update.viewportChanged || plugin.forceViewUpdate) {
|
||||
this.decorations = this.buildDecorations(update.view);
|
||||
plugin.forceViewUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
buildDecorations(view: EditorView): DecorationSet {
|
||||
|
||||
if (!plugin.settings.enabled) {
|
||||
if (!plugin.settings.enabled || plugin.regex == null) {
|
||||
return Decoration.none;
|
||||
}
|
||||
|
||||
|
|
@ -210,17 +176,15 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
//const words = ["just", "sample", "is"];
|
||||
|
||||
//const sentenceRegex = /\bbasically\b|\btext\b/gi
|
||||
|
||||
|
||||
let match;
|
||||
|
||||
for (const { from, to } of view.visibleRanges) {
|
||||
|
||||
|
||||
// IMPORTANT: Reset lastIndex for global regexes when searching new strings/slices
|
||||
plugin.regex.lastIndex = 0;
|
||||
|
||||
plugin.regex.lastIndex = 0; // Important
|
||||
|
||||
const doc = view.state.doc
|
||||
|
||||
|
|
@ -228,13 +192,17 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
|
||||
while ((match = plugin.regex.exec(visibleText)) !== null) {
|
||||
|
||||
//console.log(text.length);
|
||||
const matchingRule: Rule = plugin.rules.getRuleByMatchString(match[0]);
|
||||
|
||||
let start: number;
|
||||
start = match.index + from + matchingRule.highlightOffset;
|
||||
|
||||
start = match.index + from;
|
||||
|
||||
const end = start + match[0].length;
|
||||
let end: number;
|
||||
if (matchingRule.highlightLength != null) {
|
||||
end = start + matchingRule.highlightLength - matchingRule.highlightOffset
|
||||
} else {
|
||||
end = start + match[0].length - matchingRule.highlightOffset;
|
||||
}
|
||||
|
||||
if (skipRanges.some(range => start >= range.min && start <= range.max)) {
|
||||
continue;
|
||||
|
|
@ -243,11 +211,11 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
|
||||
|
||||
|
||||
if(plugin.settings.enableTooltips) {
|
||||
if (plugin.settings.enableTooltips) {
|
||||
builder.add(start, end, Decoration.mark({
|
||||
class: `fluff${formattingClass}`,
|
||||
attributes: {
|
||||
'aria-label': "Much longer \nworld",
|
||||
'aria-label': matchingRule.match,
|
||||
'data-tooltip-position': "bottom"
|
||||
}
|
||||
}));
|
||||
|
|
@ -258,36 +226,13 @@ export default class CutTheFluffPlugin extends Plugin {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
while ((match = sentenceRegex.exec(text)) !== null) {
|
||||
|
||||
let start: number;
|
||||
|
||||
start = match.index;
|
||||
|
||||
const end = start + match[0].length;
|
||||
|
||||
if (skipRanges.some(range => start >= range.min && start <= range.max)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
builder.add(start, end, Decoration.mark({
|
||||
class: 'fluff',
|
||||
}));
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
return builder.finish();
|
||||
}
|
||||
|
|
@ -341,12 +286,11 @@ class CutTheFluggSettingsTab extends PluginSettingTab {
|
|||
dropdown.onChange(async (newValue) => {
|
||||
|
||||
this.plugin.settings.highlightStyle = newValue;
|
||||
// Save the updated settings
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Enable tooltips')
|
||||
|
||||
|
|
@ -356,7 +300,7 @@ class CutTheFluggSettingsTab extends PluginSettingTab {
|
|||
this.plugin.settings.enableTooltips = value;
|
||||
await this.plugin.saveSettings();
|
||||
}));
|
||||
*/
|
||||
|
||||
|
||||
new Setting(containerEl).setName('Built-in rulesets').setHeading();
|
||||
|
||||
|
|
@ -391,7 +335,7 @@ class CutTheFluggSettingsTab extends PluginSettingTab {
|
|||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Redudancies')
|
||||
.setName('Redundancies')
|
||||
.setDesc('eg. combine together, basic fundamentals, critically important, final conclusion')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.enableRulesetRedudancies) // Set the initial state of the toggle from loaded settings
|
||||
|
|
|
|||
240
rulesets.ts
240
rulesets.ts
|
|
@ -5,88 +5,160 @@ export interface Rulesets {
|
|||
redundancies: Record<string, string>;
|
||||
}
|
||||
|
||||
export const RULESETS: Rulesets = {
|
||||
weakQualifiers:{
|
||||
"a bit": "",
|
||||
"a little": "",
|
||||
"actual": "",
|
||||
"actually": "",
|
||||
"basically": "",
|
||||
"just": "",
|
||||
"kind of": "",
|
||||
"like": "",
|
||||
"literally": "",
|
||||
"quite": "",
|
||||
"really": "",
|
||||
"simply": "",
|
||||
"sort of": "",
|
||||
"very": "",
|
||||
"somewhat": "",
|
||||
},
|
||||
jargon: {
|
||||
"at the end of the day": "",
|
||||
"boil the ocean": "",
|
||||
"double-edged sword": "",
|
||||
"going forward": "",
|
||||
"I beg to differ": "",
|
||||
"ideate": "",
|
||||
"move the needle": "",
|
||||
"moving forward": "",
|
||||
"paradigm": "",
|
||||
"paradigm shift": "",
|
||||
"rightsizing": "",
|
||||
"singing from the same hymn sheet": "",
|
||||
"touch base": "",
|
||||
"unpack": "",
|
||||
},
|
||||
complexity: {
|
||||
"as of yet": "",
|
||||
"at the present time": "",
|
||||
"close proximity": "",
|
||||
"commence": "",
|
||||
"deem": "",
|
||||
"dialogue": "",
|
||||
"due to the fact that": "",
|
||||
"endeavor": "",
|
||||
"endeavour": "",
|
||||
"enumerate": "",
|
||||
"equitable": "",
|
||||
"erroneous": "",
|
||||
"facilitate": "",
|
||||
"For all intents and purposes": "",
|
||||
"henceforth": "",
|
||||
"herewith": "",
|
||||
"honestly": "",
|
||||
"in a sense": "",
|
||||
"in lieu of": "",
|
||||
"in my humble opinion": "",
|
||||
"in order to": "",
|
||||
"in regard to": "",
|
||||
"in relation to": "",
|
||||
"in the event of": "",
|
||||
"inception": "",
|
||||
"leverage": "",
|
||||
"numerous": "",
|
||||
"per se": "",
|
||||
"pertaining to": "",
|
||||
"prior to": "",
|
||||
"subsequently": "",
|
||||
"utilise": "",
|
||||
"utilize": "",
|
||||
"of the opinion that": "",
|
||||
"with reference to": "",
|
||||
"with the exception of": "",
|
||||
"i might add": "",
|
||||
"it is interesting to note": "",
|
||||
},
|
||||
redundancies: {
|
||||
"combine together": "",
|
||||
"successfully complete": "",
|
||||
"basic fundamentals": "",
|
||||
"each and every": "",
|
||||
"in the event that": "",
|
||||
"one and the same": "",
|
||||
"critically important": "",
|
||||
"final conclusion": "",
|
||||
export const enum RuleType {
|
||||
WeakQualifier = "WeakQualifier",
|
||||
Jargon = "Jaron",
|
||||
Complexity = "Complexity",
|
||||
Redundancy = "Redudancy",
|
||||
Custom = "Custom"
|
||||
}
|
||||
|
||||
export class Rule {
|
||||
match: string;
|
||||
//alternatives: string[];
|
||||
highlightLength: number | null;
|
||||
highlightOffset: number;
|
||||
type: RuleType;
|
||||
|
||||
constructor(type: RuleType, match: string, highLightOffset: number = 0, highlightLength: number | null = null) {
|
||||
this.type = type;
|
||||
this.match = match.toLowerCase();
|
||||
this.highlightOffset = highLightOffset;
|
||||
this.highlightLength = highlightLength;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export class Rules {
|
||||
rules: Record<string, Rule> = {};
|
||||
customRules: Record<string, Rule> = {};
|
||||
|
||||
constructor() {
|
||||
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "a bit"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "a little"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "actual"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "actually"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "basically"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "just"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "kind of"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "like"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "literally"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "quite"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "really"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "simply"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "sort of"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "very"));
|
||||
this.addRule(new Rule(RuleType.WeakQualifier, "somewhat"));
|
||||
|
||||
this.addRule(new Rule(RuleType.Jargon, "at the end of the day"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "boil the ocean"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "double-edged sword"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "going forward"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "i beg to differ"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "ideate"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "move the needle"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "moving forward"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "paradigm"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "paradigm shift"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "rightsizing"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "singing from the same hymn sheet"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "touch base"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "unpack"));
|
||||
this.addRule(new Rule(RuleType.Jargon, "north star"));
|
||||
|
||||
|
||||
|
||||
this.addRule(new Rule(RuleType.Complexity, "as of yet"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "at the present time"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "close proximity"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "commence"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "deem"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "dialogue"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "due to the fact that"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "endeavor"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "endeavour"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "enumerate"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "equitable"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "erroneous"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "facilitate"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "For all intents and purposes"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "henceforth"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "herewith"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "honestly"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in a sense"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in lieu of"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in my humble opinion"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in order to"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in regard to"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in relation to"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "in the event of"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "inception"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "leverage"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "numerous"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "per se"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "pertaining to"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "prior to"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "subsequently"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "utilise"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "utilize"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "of the opinion that"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "with reference to"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "with the exception of"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "i might add"));
|
||||
this.addRule(new Rule(RuleType.Complexity, "it is interesting to note"));
|
||||
|
||||
this.addRule(new Rule(RuleType.Redundancy, "combine together", 7));
|
||||
this.addRule(new Rule(RuleType.Redundancy, "critically important", 8));
|
||||
this.addRule(new Rule(RuleType.Redundancy, "each and every", 0, 9));
|
||||
|
||||
|
||||
this.addRule(new Rule(RuleType.Redundancy, "successfully complete", 0, 13));
|
||||
this.addRule(new Rule(RuleType.Redundancy, "basic fundamentals"));
|
||||
this.addRule(new Rule(RuleType.Redundancy, "in the event that"));
|
||||
this.addRule(new Rule(RuleType.Redundancy, "one and the same", 0, 8));
|
||||
this.addRule(new Rule(RuleType.Redundancy, "final conclusion", 0, 6));
|
||||
|
||||
}
|
||||
|
||||
private addRule(rule: Rule) : void {
|
||||
this.rules[rule.match] = rule;
|
||||
}
|
||||
|
||||
public resetCustomRules() : void {
|
||||
this.customRules = {};
|
||||
}
|
||||
|
||||
public addCustomRule(match: string) : void {
|
||||
this.customRules[match] = new Rule(RuleType.Custom, match);
|
||||
}
|
||||
|
||||
public getRuleByMatchString(match: string): Rule {
|
||||
|
||||
match = match.toLowerCase();
|
||||
|
||||
if(match in this.rules) {
|
||||
return this.rules[match];
|
||||
} else {
|
||||
return this.customRules[match];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public getMatchStrings(types: RuleType[], exclusions: string[]): string[] {
|
||||
let toReturn: string[] = [];
|
||||
|
||||
for (let key in this.rules) {
|
||||
if (types.includes(this.rules[key].type) && !exclusions.includes(key)) {
|
||||
toReturn.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
for (let key in this.customRules) {
|
||||
toReturn.push(key);
|
||||
}
|
||||
|
||||
// Sort by length so more precise matches take priority
|
||||
return toReturn.sort((a, b) => b.length - a.length);;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue