mirror of
https://github.com/calfmoon/node-factor.git
synced 2026-07-22 05:42:24 +00:00
Merge branch 'modularize'
This commit is contained in:
commit
99cb882ff3
7 changed files with 299 additions and 226 deletions
67
src/calculator.ts
Normal file
67
src/calculator.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
import { App } from "obsidian";
|
||||
|
||||
import { NodeFactorSettings, ObsidianNode } from "types";
|
||||
|
||||
export default class Calculations {
|
||||
private app: App;
|
||||
private settings: NodeFactorSettings;
|
||||
|
||||
constructor(app: App, settings: NodeFactorSettings) {
|
||||
this.app = app;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
calcNodeWeight(node: ObsidianNode): number {
|
||||
const settings = this.settings;
|
||||
let weight = 0;
|
||||
|
||||
const manualFileData = settings.manual.find(
|
||||
(manualFileData) => manualFileData.id == node.id,
|
||||
);
|
||||
if (manualFileData != null) {
|
||||
return manualFileData.weight;
|
||||
}
|
||||
|
||||
weight += Object.keys(node.reverse).length * settings.bwdMultiplier;
|
||||
if (settings.fwdTree) {
|
||||
weight +=
|
||||
this.fwdNodeTreeSize(node, new Set()) * settings.fwdMultiplier;
|
||||
} else {
|
||||
weight += Object.keys(node.forward).length * settings.fwdMultiplier;
|
||||
}
|
||||
|
||||
if (settings.lettersPerWt != 0) {
|
||||
weight += this.letterCount(node) / settings.lettersPerWt;
|
||||
}
|
||||
|
||||
return Math.round(weight);
|
||||
}
|
||||
|
||||
private letterCount(node: ObsidianNode): number {
|
||||
const file = this.app.vault.getFileByPath(node.id);
|
||||
if (file == null || file.extension != "md") return 0;
|
||||
|
||||
return file.stat.size;
|
||||
}
|
||||
|
||||
private fwdNodeTreeSize(
|
||||
node: ObsidianNode,
|
||||
antiLoopSet: Set<string>,
|
||||
): number {
|
||||
let size = 0;
|
||||
antiLoopSet.add(node.id);
|
||||
|
||||
Object.entries(node.forward).forEach(([key, value]) => {
|
||||
// @ts-ignore
|
||||
const childNode: ObsidianNode = value.target;
|
||||
|
||||
// Prevents looping if A -> B -> C -> D -> B
|
||||
if (!antiLoopSet.has(key)) {
|
||||
size++;
|
||||
const childSize = this.fwdNodeTreeSize(childNode, antiLoopSet);
|
||||
size += childSize;
|
||||
}
|
||||
});
|
||||
return size;
|
||||
}
|
||||
}
|
||||
63
src/main.ts
63
src/main.ts
|
|
@ -1,7 +1,8 @@
|
|||
import { Plugin } from "obsidian";
|
||||
|
||||
import { ObsidianNode, NodeFactorSettings, DEFAULT_SETTINGS } from "./types";
|
||||
import NodeFactorSettingTab from "./settings";
|
||||
import { ObsidianNode, NodeFactorSettings, DEFAULT_SETTINGS } from "types";
|
||||
import NodeFactorSettingTab from "settings";
|
||||
import Calculator from "calculator";
|
||||
|
||||
export default class NodeFactor extends Plugin {
|
||||
settings: NodeFactorSettings;
|
||||
|
|
@ -56,12 +57,14 @@ export default class NodeFactor extends Plugin {
|
|||
// if graph view is initially opened when opening obsidian
|
||||
clearTimeout(this.timeoutId);
|
||||
this.timeoutId = setTimeout(() => {
|
||||
const calculator = new Calculator(this.app, this.settings);
|
||||
|
||||
nodes.forEach((node, _i) => {
|
||||
let weight = 0;
|
||||
if (this.sizeCache.get(node.id) != undefined) {
|
||||
weight = this.sizeCache.get(node.id) as number;
|
||||
} else {
|
||||
weight = this.calcNodeWeight(node);
|
||||
weight = calculator.calcNodeWeight(node);
|
||||
this.sizeCache.set(node.id, weight);
|
||||
}
|
||||
node.weight = weight;
|
||||
|
|
@ -69,60 +72,6 @@ export default class NodeFactor extends Plugin {
|
|||
}, 500);
|
||||
}
|
||||
|
||||
private calcNodeWeight(node: ObsidianNode): number {
|
||||
const settings = this.settings;
|
||||
let weight = 0;
|
||||
|
||||
const manualFileData = settings.manual.find(
|
||||
(manualFileData) => manualFileData.id == node.id,
|
||||
);
|
||||
if (manualFileData != null) {
|
||||
return manualFileData.weight;
|
||||
}
|
||||
|
||||
weight += Object.keys(node.reverse).length * settings.bwdMultiplier;
|
||||
if (settings.fwdTree) {
|
||||
weight +=
|
||||
this.fwdNodeTreeSize(node, new Set()) * settings.fwdMultiplier;
|
||||
} else {
|
||||
weight += Object.keys(node.forward).length * settings.fwdMultiplier;
|
||||
}
|
||||
|
||||
if (settings.lettersPerWt != 0) {
|
||||
weight += this.letterCount(node) / settings.lettersPerWt;
|
||||
}
|
||||
|
||||
return Math.round(weight);
|
||||
}
|
||||
|
||||
private letterCount(node: ObsidianNode): number {
|
||||
const file = this.app.vault.getFileByPath(node.id);
|
||||
if (file == null || file.extension != "md") return 0;
|
||||
|
||||
return file.stat.size;
|
||||
}
|
||||
|
||||
private fwdNodeTreeSize(
|
||||
node: ObsidianNode,
|
||||
antiLoopSet: Set<string>,
|
||||
): number {
|
||||
let size = 0;
|
||||
antiLoopSet.add(node.id);
|
||||
|
||||
Object.entries(node.forward).forEach(([key, value]) => {
|
||||
// @ts-ignore
|
||||
const childNode: ObsidianNode = value.target;
|
||||
|
||||
// Prevents looping if A -> B -> C -> D -> B
|
||||
if (!antiLoopSet.has(key)) {
|
||||
size++;
|
||||
const childSize = this.fwdNodeTreeSize(childNode, antiLoopSet);
|
||||
size += childSize;
|
||||
}
|
||||
});
|
||||
return size;
|
||||
}
|
||||
|
||||
recalculateSize() {
|
||||
this.sizeCache.clear();
|
||||
this.updateGraph();
|
||||
|
|
|
|||
169
src/settings.ts
169
src/settings.ts
|
|
@ -1,169 +0,0 @@
|
|||
import {
|
||||
App,
|
||||
ButtonComponent,
|
||||
Notice,
|
||||
PluginSettingTab,
|
||||
SearchComponent,
|
||||
Setting,
|
||||
SliderComponent,
|
||||
} from "obsidian";
|
||||
|
||||
import NodeFactor from "./main";
|
||||
import FileSuggest from "./file-suggest";
|
||||
import { FileData } from "./types";
|
||||
|
||||
export default class NodeFactorSettingTab extends PluginSettingTab {
|
||||
plugin: NodeFactor;
|
||||
|
||||
constructor(app: App, plugin: NodeFactor) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Programatically set size")
|
||||
.setHeading();
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Forward link weight multiplier")
|
||||
.setDesc("Multiplier for forward links weight (0 to disable).")
|
||||
.addSlider((slider) => {
|
||||
slider
|
||||
.setLimits(0, 20, 1)
|
||||
.setDynamicTooltip()
|
||||
.setValue(this.plugin.settings.fwdMultiplier)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.fwdMultiplier = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Travel forward tree")
|
||||
.setDesc(
|
||||
"Travel forward and add all other nodes to determine final node size.",
|
||||
)
|
||||
.addToggle((toggle) => {
|
||||
toggle
|
||||
.setValue(this.plugin.settings.fwdTree)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.fwdTree = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Backward link weight multiplier")
|
||||
.setDesc("Multiplier for backward links weight (0 to disable).")
|
||||
.addSlider((slider) => {
|
||||
slider
|
||||
.setLimits(0, 20, 1)
|
||||
.setDynamicTooltip()
|
||||
.setValue(this.plugin.settings.bwdMultiplier)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.bwdMultiplier = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName("Character per weight")
|
||||
.setDesc(
|
||||
"Add 1 weight to node size per no of given character (0 to disable).",
|
||||
)
|
||||
.addSlider((slider) => {
|
||||
slider
|
||||
.setLimits(0, 5000, 100)
|
||||
.setDynamicTooltip()
|
||||
.setValue(this.plugin.settings.lettersPerWt)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.lettersPerWt = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
new Setting(containerEl).setName("Manually set size").setHeading();
|
||||
|
||||
let selectedWeight: SliderComponent;
|
||||
let selectedFile: SearchComponent;
|
||||
let submitButton: ButtonComponent;
|
||||
new Setting(containerEl)
|
||||
.setName("Add new weight")
|
||||
.setDesc("Weight added here overrides everything else.")
|
||||
.addSearch((search) => {
|
||||
new FileSuggest(this.app, search.inputEl);
|
||||
selectedFile = search;
|
||||
search
|
||||
.setPlaceholder("Enter file name")
|
||||
.onChange(async (value) => {
|
||||
submitButton.setDisabled(value.length === 0);
|
||||
});
|
||||
})
|
||||
.addSlider((slider) => {
|
||||
selectedWeight = slider;
|
||||
slider.setLimits(0, 100, 5).setDynamicTooltip().setValue(0);
|
||||
})
|
||||
.addButton((button) => {
|
||||
submitButton = button;
|
||||
button
|
||||
.setDisabled(true)
|
||||
.setButtonText("Add")
|
||||
.setTooltip("Click to add")
|
||||
.onClick(async () => {
|
||||
const enteredFileData: FileData = {
|
||||
id: selectedFile.getValue(),
|
||||
weight: selectedWeight.getValue(),
|
||||
};
|
||||
selectedWeight.setValue(0);
|
||||
selectedFile.setValue("");
|
||||
|
||||
const fileExists = this.plugin.settings.manual.find(
|
||||
(foundFile) => foundFile.id == enteredFileData.id,
|
||||
);
|
||||
|
||||
if (fileExists) {
|
||||
new Notice(
|
||||
"That file's size has already been entered," +
|
||||
" remove it first to change weight.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.plugin.settings.manual.push(enteredFileData);
|
||||
await this.plugin.saveSettings();
|
||||
new Notice("Manual size added");
|
||||
|
||||
// Rerender display
|
||||
this.display();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
// Display all manually added weights
|
||||
this.plugin.settings.manual.forEach((value: FileData) => {
|
||||
new Setting(containerEl)
|
||||
.setName(value.id)
|
||||
.setDesc(`Weight: ${String(value.weight)}`)
|
||||
.addButton((button) => {
|
||||
button
|
||||
.setIcon("trash")
|
||||
.setTooltip("Remove manually added size")
|
||||
.onClick(async () => {
|
||||
this.plugin.settings.manual.remove(value);
|
||||
await this.plugin.saveSettings();
|
||||
|
||||
this.display();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
26
src/settings/index.ts
Normal file
26
src/settings/index.ts
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import { App, PluginSettingTab } from "obsidian";
|
||||
|
||||
import NodeFactor from "main";
|
||||
|
||||
import ManualSetting from "./manual";
|
||||
import ProgrameticalSetting from "./programetical";
|
||||
|
||||
export default class NodeFactorSettingTab extends PluginSettingTab {
|
||||
private plugin: NodeFactor;
|
||||
|
||||
constructor(app: App, plugin: NodeFactor) {
|
||||
super(app, plugin);
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { plugin, containerEl, app } = this;
|
||||
containerEl.empty();
|
||||
|
||||
new ProgrameticalSetting(plugin, containerEl).display();
|
||||
|
||||
new ManualSetting(app, plugin, containerEl, () =>
|
||||
this.display(),
|
||||
).display();
|
||||
}
|
||||
}
|
||||
115
src/settings/manual.ts
Normal file
115
src/settings/manual.ts
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import {
|
||||
App,
|
||||
ButtonComponent,
|
||||
Notice,
|
||||
SearchComponent,
|
||||
Setting,
|
||||
SliderComponent,
|
||||
} from "obsidian";
|
||||
|
||||
import NodeFactor from "main";
|
||||
import { FileData } from "types";
|
||||
|
||||
import FileSuggest from "./file-suggest";
|
||||
|
||||
export default class ManualSetting {
|
||||
private app: App;
|
||||
private plugin: NodeFactor;
|
||||
private containerEl: HTMLElement;
|
||||
private refreshDisplay: () => void;
|
||||
|
||||
constructor(
|
||||
app: App,
|
||||
plugin: NodeFactor,
|
||||
containerEl: HTMLElement,
|
||||
refreshDisplay: () => void,
|
||||
) {
|
||||
this.app = app;
|
||||
this.plugin = plugin;
|
||||
this.containerEl = containerEl;
|
||||
this.refreshDisplay = refreshDisplay;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
new Setting(this.containerEl).setName("Manually set size").setHeading();
|
||||
|
||||
let selectedWeight: SliderComponent;
|
||||
let selectedFile: SearchComponent;
|
||||
let submitButton: ButtonComponent;
|
||||
|
||||
const addWt = new Setting(this.containerEl)
|
||||
.setName("Add new weight")
|
||||
.setDesc("Weight added here overrides everything else.");
|
||||
|
||||
addWt.addSearch((search) => {
|
||||
new FileSuggest(this.app, search.inputEl);
|
||||
selectedFile = search;
|
||||
search.setPlaceholder("Enter file name");
|
||||
search.onChange(async (value) => {
|
||||
submitButton.setDisabled(value.length === 0);
|
||||
});
|
||||
});
|
||||
|
||||
addWt.addSlider((slider) => {
|
||||
selectedWeight = slider;
|
||||
slider.setLimits(0, 100, 5);
|
||||
slider.setDynamicTooltip();
|
||||
slider.setValue(0);
|
||||
});
|
||||
|
||||
addWt.addButton((button) => {
|
||||
submitButton = button;
|
||||
button.setDisabled(true);
|
||||
button.setButtonText("Add");
|
||||
button.setTooltip("Click to add new manual size");
|
||||
|
||||
button.onClick(async () => {
|
||||
const enteredFileData: FileData = {
|
||||
id: selectedFile.getValue(),
|
||||
weight: selectedWeight.getValue(),
|
||||
};
|
||||
selectedWeight.setValue(0);
|
||||
selectedFile.setValue("");
|
||||
|
||||
const fileExists = this.plugin.settings.manual.find(
|
||||
(foundFile) => foundFile.id == enteredFileData.id,
|
||||
);
|
||||
|
||||
if (fileExists != undefined) {
|
||||
new Notice(
|
||||
"That file's size has already been entered," +
|
||||
" remove it first to change weight.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.plugin.settings.manual.push(enteredFileData);
|
||||
await this.plugin.saveSettings();
|
||||
new Notice("New size added manually");
|
||||
|
||||
this.refreshDisplay();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
// Display all manually added weights & option to remove them
|
||||
this.plugin.settings.manual.forEach((value: FileData) => {
|
||||
const manualDisplay = new Setting(this.containerEl)
|
||||
.setName(value.id)
|
||||
.setDesc(`Weight: ${String(value.weight)}`);
|
||||
|
||||
manualDisplay.addButton((button) => {
|
||||
button.setIcon("trash");
|
||||
button.setTooltip("Remove manually added size");
|
||||
|
||||
button.onClick(async () => {
|
||||
this.plugin.settings.manual.remove(value);
|
||||
await this.plugin.saveSettings();
|
||||
|
||||
this.refreshDisplay();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
85
src/settings/programetical.ts
Normal file
85
src/settings/programetical.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import { Setting } from "obsidian";
|
||||
|
||||
import NodeFactor from "main";
|
||||
|
||||
export default class ProgrameticalSetting {
|
||||
private plugin: NodeFactor;
|
||||
private containerEl: HTMLElement;
|
||||
|
||||
constructor(plugin: NodeFactor, containerEl: HTMLElement) {
|
||||
this.plugin = plugin;
|
||||
this.containerEl = containerEl;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
new Setting(this.containerEl)
|
||||
.setName("Programatically set size")
|
||||
.setHeading();
|
||||
|
||||
const fwdLinkWt = new Setting(this.containerEl)
|
||||
.setName("Forward link weight multiplier")
|
||||
.setDesc("Multiplier for forward links weight (0 to disable).");
|
||||
|
||||
fwdLinkWt.addSlider((slider) => {
|
||||
slider.setLimits(0, 20, 1);
|
||||
slider.setDynamicTooltip();
|
||||
slider.setValue(this.plugin.settings.fwdMultiplier);
|
||||
|
||||
slider.onChange(async (value) => {
|
||||
this.plugin.settings.fwdMultiplier = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
const travelFwdTree = new Setting(this.containerEl)
|
||||
.setName("Travel forward tree")
|
||||
.setDesc(
|
||||
"Travel forward and add all other nodes to determine final node size.",
|
||||
);
|
||||
|
||||
travelFwdTree.addToggle((toggle) => {
|
||||
toggle.setValue(this.plugin.settings.fwdTree);
|
||||
|
||||
toggle.onChange(async (value) => {
|
||||
this.plugin.settings.fwdTree = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
const bwdLinkWt = new Setting(this.containerEl)
|
||||
.setName("Backward link weight multiplier")
|
||||
.setDesc("Multiplier for backward links weight (0 to disable).");
|
||||
|
||||
bwdLinkWt.addSlider((slider) => {
|
||||
slider.setLimits(0, 20, 1);
|
||||
slider.setDynamicTooltip();
|
||||
slider.setValue(this.plugin.settings.bwdMultiplier);
|
||||
|
||||
slider.onChange(async (value) => {
|
||||
this.plugin.settings.bwdMultiplier = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
|
||||
const charWt = new Setting(this.containerEl)
|
||||
.setName("Character per weight")
|
||||
.setDesc(
|
||||
"Add 1 weight to node size per no of given character (0 to disable).",
|
||||
);
|
||||
|
||||
charWt.addSlider((slider) => {
|
||||
slider.setLimits(0, 5000, 100);
|
||||
slider.setDynamicTooltip();
|
||||
slider.setValue(this.plugin.settings.lettersPerWt);
|
||||
|
||||
slider.onChange(async (value) => {
|
||||
this.plugin.settings.lettersPerWt = value;
|
||||
await this.plugin.saveSettings();
|
||||
this.plugin.recalculateSize();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue