mirror of
https://github.com/calfmoon/node-factor.git
synced 2026-07-22 12:20:32 +00:00
Compare commits
20 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d5d1538c9 | ||
|
|
b3dfbb089b | ||
|
|
99cb882ff3 | ||
|
|
aa5f5cb5e5 | ||
|
|
dbdf7d2a90 | ||
|
|
8ba7f85b55 | ||
|
|
ca82866158 | ||
|
|
a36f1c9ed0 | ||
|
|
cd5f4c97c9 | ||
|
|
f23e337178 | ||
|
|
9d2b9769c4 | ||
|
|
d02a58be62 | ||
|
|
43ea5c276a | ||
|
|
3c56ee6e74 | ||
|
|
e0279c3845 | ||
|
|
d212d1f57f | ||
|
|
fd824ea406 | ||
|
|
a213c8b3c5 | ||
|
|
aa0987082e | ||
|
|
b43c8dcafc |
19 changed files with 4304 additions and 845 deletions
|
|
@ -1,3 +0,0 @@
|
||||||
node_modules/
|
|
||||||
|
|
||||||
main.js
|
|
||||||
23
.eslintrc
23
.eslintrc
|
|
@ -1,23 +0,0 @@
|
||||||
{
|
|
||||||
"root": true,
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"env": { "node": true },
|
|
||||||
"plugins": [
|
|
||||||
"@typescript-eslint"
|
|
||||||
],
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended"
|
|
||||||
],
|
|
||||||
"parserOptions": {
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"no-unused-vars": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
|
||||||
"@typescript-eslint/ban-ts-comment": "off",
|
|
||||||
"no-prototype-builtins": "off",
|
|
||||||
"@typescript-eslint/no-empty-function": "off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
.github/workflows/lint.yml
vendored
Normal file
28
.github/workflows/lint.yml
vendored
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
name: Node.js build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["**"]
|
||||||
|
pull_request:
|
||||||
|
branches: ["**"]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [20.x, 22.x]
|
||||||
|
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: "npm"
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm run build --if-present
|
||||||
|
- run: npm run lint
|
||||||
|
|
||||||
13
README.md
13
README.md
|
|
@ -1,8 +1,15 @@
|
||||||
# Node Factor
|
# Node Factor
|
||||||
This plugin helps you customize the factors that effect node size in obsidian graph view.
|
This plugin helps you customize the factors that effect node size in obsidian graph view.
|
||||||
The factors include, letter count, forward & backward weight, and forward tree weight.
|
The factors include:
|
||||||
|
- Letter count in a file.
|
||||||
|
- Weight of links coming forward and/or backward out of a file.
|
||||||
|
- Whether we should count every descendant coming forward out of a file or just the children.
|
||||||
|
- You can manually add size for certain files too.
|
||||||
|
|
||||||
|
## Demo
|
||||||
<img src="./screenshots/1.jpeg">
|
<img src="./screenshots/1.jpeg">
|
||||||
<img src="./screenshots/2.jpeg">
|
<img src="./screenshots/2.jpeg">
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
1. Search for "Node Factor" in Obsidian's community plugin browser.
|
1. Search for "Node Factor" in Obsidian's community plugin browser.
|
||||||
2. Install it.
|
2. Install it.
|
||||||
|
|
@ -14,9 +21,13 @@ The factors include, letter count, forward & backward weight, and forward tree w
|
||||||
| Travel forward tree | Determines if forward weight is decided by just the immediate nodes coming out or everything after it | off |
|
| Travel forward tree | Determines if forward weight is decided by just the immediate nodes coming out or everything after it | off |
|
||||||
| Backward link weight multiplier | Weight of single link coming backward out of a node | 1 |
|
| Backward link weight multiplier | Weight of single link coming backward out of a node | 1 |
|
||||||
| Character per weight | Given number of letters give 1 weight | 0 |
|
| Character per weight | Given number of letters give 1 weight | 0 |
|
||||||
|
| Manually Set Weight | Manually set weight of any file, weight set here overrides everything else | empty set |
|
||||||
|
|
||||||
## Author
|
## Author
|
||||||
CalfMoon: [Email](kritagyabhattarai@proton.me), [Github](https://github.com/CalfMoon)
|
CalfMoon: [Email](kritagyabhattarai@proton.me), [Github](https://github.com/CalfMoon)
|
||||||
|
|
||||||
## Bug Reports
|
## Bug Reports
|
||||||
This project is still new and might have a few bugs. For bug reports use this repo's Issues section.
|
This project is still new and might have a few bugs. For bug reports use this repo's Issues section.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
MIT, see [LICENSE](LICENSE).
|
MIT, see [LICENSE](LICENSE).
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
import esbuild from "esbuild";
|
import esbuild from "esbuild";
|
||||||
import process from "process";
|
import process from "process";
|
||||||
import builtins from "builtin-modules";
|
import { builtinModules } from 'node:module';
|
||||||
|
|
||||||
const banner = `/*
|
const banner =
|
||||||
|
`/*
|
||||||
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
||||||
if you want to view the source, please visit the github repository of this plugin
|
if you want to view the source, please visit the github repository of this plugin
|
||||||
*/
|
*/
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const prod = process.argv[2] === "production";
|
const prod = (process.argv[2] === "production");
|
||||||
|
|
||||||
const context = await esbuild.context({
|
const context = await esbuild.context({
|
||||||
banner: {
|
banner: {
|
||||||
|
|
@ -30,8 +31,7 @@ const context = await esbuild.context({
|
||||||
"@lezer/common",
|
"@lezer/common",
|
||||||
"@lezer/highlight",
|
"@lezer/highlight",
|
||||||
"@lezer/lr",
|
"@lezer/lr",
|
||||||
...builtins,
|
...builtinModules],
|
||||||
],
|
|
||||||
format: "cjs",
|
format: "cjs",
|
||||||
target: "es2018",
|
target: "es2018",
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
|
|
|
||||||
34
eslint.config.mts
Normal file
34
eslint.config.mts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
import obsidianmd from "eslint-plugin-obsidianmd";
|
||||||
|
import globals from "globals";
|
||||||
|
import { globalIgnores } from "eslint/config";
|
||||||
|
|
||||||
|
export default tseslint.config(
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
projectService: {
|
||||||
|
allowDefaultProject: [
|
||||||
|
'eslint.config.js',
|
||||||
|
'manifest.json'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
tsconfigRootDir: import.meta.dirname,
|
||||||
|
extraFileExtensions: ['.json']
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...obsidianmd.configs.recommended,
|
||||||
|
globalIgnores([
|
||||||
|
"node_modules",
|
||||||
|
"dist",
|
||||||
|
"esbuild.config.mjs",
|
||||||
|
"eslint.config.js",
|
||||||
|
"version-bump.mjs",
|
||||||
|
"versions.json",
|
||||||
|
"main.js",
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "node-factor",
|
"id": "node-factor",
|
||||||
"name": "Node Factor",
|
"name": "Node Factor",
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "Customize factors effecting node size in graph.",
|
"description": "Customize factors effecting node size in graph.",
|
||||||
"author": "CalfMoon",
|
"author": "CalfMoon",
|
||||||
|
|
|
||||||
4466
package-lock.json
generated
4466
package-lock.json
generated
File diff suppressed because it is too large
Load diff
22
package.json
22
package.json
|
|
@ -1,24 +1,30 @@
|
||||||
{
|
{
|
||||||
"name": "node-factor",
|
"name": "node-factor",
|
||||||
"version": "2.1.0",
|
"version": "3.0.0",
|
||||||
"description": "Customize factors effecting node size in graph.",
|
"description": "Customize factors effecting node size in graph.",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node esbuild.config.mjs",
|
"dev": "node esbuild.config.mjs",
|
||||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
"version": "node version-bump.mjs && git add manifest.json versions.json",
|
||||||
|
"lint": "eslint ."
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "CalfMoon",
|
"author": "CalfMoon",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@eslint/js": "9.30.1",
|
||||||
"@types/node": "^16.11.6",
|
"@types/node": "^16.11.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
"esbuild": "0.28.1",
|
||||||
"@typescript-eslint/parser": "^8.57.2",
|
"eslint": "^9.39.4",
|
||||||
"builtin-modules": "3.3.0",
|
"eslint-plugin-obsidianmd": "0.1.9",
|
||||||
"esbuild": "^0.27.4",
|
"globals": "^14.0.0",
|
||||||
"obsidian": "latest",
|
"jiti": "2.6.1",
|
||||||
"tslib": "2.4.0",
|
"tslib": "2.4.0",
|
||||||
"typescript": "4.7.4"
|
"typescript": "^5.8.3",
|
||||||
|
"typescript-eslint": "^8.35.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"obsidian": "latest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
71
src/main.ts
71
src/main.ts
|
|
@ -1,7 +1,8 @@
|
||||||
import { Plugin } from "obsidian";
|
import { Plugin } from "obsidian";
|
||||||
|
|
||||||
import { ObsidianNode, NodeFactorSettings, DEFAULT_SETTINGS } from "./types";
|
import { ObsidianNode, NodeFactorSettings, DEFAULT_SETTINGS } from "types";
|
||||||
import NodeFactorSettingTab from "./settings";
|
import NodeFactorSettingTab from "settings";
|
||||||
|
import Calculator from "calculator";
|
||||||
|
|
||||||
export default class NodeFactor extends Plugin {
|
export default class NodeFactor extends Plugin {
|
||||||
settings: NodeFactorSettings;
|
settings: NodeFactorSettings;
|
||||||
|
|
@ -11,10 +12,12 @@ export default class NodeFactor extends Plugin {
|
||||||
this.addSettingTab(new NodeFactorSettingTab(this.app, this));
|
this.addSettingTab(new NodeFactorSettingTab(this.app, this));
|
||||||
|
|
||||||
this.registerEvent(
|
this.registerEvent(
|
||||||
this.app.workspace.on("active-leaf-change", () => {
|
this.app.workspace.on("active-leaf-change", () =>
|
||||||
// we can still use cache when only active leaf changes
|
this.updateGraph(),
|
||||||
this.updateGraph();
|
),
|
||||||
}),
|
);
|
||||||
|
this.registerEvent(
|
||||||
|
this.app.workspace.on("layout-change", () => this.updateGraph()),
|
||||||
);
|
);
|
||||||
|
|
||||||
// clear cache when there is change in the vault
|
// clear cache when there is change in the vault
|
||||||
|
|
@ -37,7 +40,7 @@ export default class NodeFactor extends Plugin {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onunload() {}
|
onunload() {}
|
||||||
|
|
||||||
private sizeCache: Map<string, number> = new Map();
|
private sizeCache: Map<string, number> = new Map();
|
||||||
private timeoutId: NodeJS.Timeout;
|
private timeoutId: NodeJS.Timeout;
|
||||||
|
|
@ -47,19 +50,21 @@ export default class NodeFactor extends Plugin {
|
||||||
if (!leaf) return;
|
if (!leaf) return;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
let nodes: Array<ObsidianNode> = leaf.view.renderer.nodes;
|
const nodes: Array<ObsidianNode> = leaf.view.renderer.nodes;
|
||||||
if (nodes.length === 0) return;
|
if (nodes.length === 0) return;
|
||||||
|
|
||||||
// Slight delay in calculations is needed to fix node size
|
// Slight delay in calculations is needed to fix node size
|
||||||
// if graph view is initially opened when opening obsidian
|
// if graph view is initially opened when opening obsidian
|
||||||
clearTimeout(this.timeoutId);
|
clearTimeout(this.timeoutId);
|
||||||
this.timeoutId = setTimeout(() => {
|
this.timeoutId = setTimeout(() => {
|
||||||
|
const calculator = new Calculator(this.app, this.settings);
|
||||||
|
|
||||||
nodes.forEach((node, _i) => {
|
nodes.forEach((node, _i) => {
|
||||||
let weight = 0;
|
let weight = 0;
|
||||||
if (this.sizeCache.get(node.id) != undefined) {
|
if (this.sizeCache.get(node.id) != undefined) {
|
||||||
weight = this.sizeCache.get(node.id) as number;
|
weight = this.sizeCache.get(node.id) as number;
|
||||||
} else {
|
} else {
|
||||||
weight = this.calcNodeWeight(node);
|
weight = calculator.calcNodeWeight(node);
|
||||||
this.sizeCache.set(node.id, weight);
|
this.sizeCache.set(node.id, weight);
|
||||||
}
|
}
|
||||||
node.weight = weight;
|
node.weight = weight;
|
||||||
|
|
@ -67,54 +72,6 @@ export default class NodeFactor extends Plugin {
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
private calcNodeWeight(node: ObsidianNode): number {
|
|
||||||
const settings = this.settings;
|
|
||||||
let weight = 0;
|
|
||||||
|
|
||||||
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)) return size;
|
|
||||||
|
|
||||||
size++;
|
|
||||||
const childSize = this.fwdNodeTreeSize(childNode, antiLoopSet);
|
|
||||||
size += childSize;
|
|
||||||
});
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
recalculateSize() {
|
recalculateSize() {
|
||||||
this.sizeCache.clear();
|
this.sizeCache.clear();
|
||||||
this.updateGraph();
|
this.updateGraph();
|
||||||
|
|
|
||||||
|
|
@ -1,78 +0,0 @@
|
||||||
import { App, PluginSettingTab, Setting } from "obsidian";
|
|
||||||
|
|
||||||
import NodeFactor from "./main";
|
|
||||||
|
|
||||||
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("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.recalculateSize();
|
|
||||||
this.plugin.settings.fwdMultiplier = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
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.recalculateSize();
|
|
||||||
this.plugin.settings.fwdTree = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
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.recalculateSize();
|
|
||||||
this.plugin.settings.bwdMultiplier = value;
|
|
||||||
await this.plugin.saveSettings();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
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();
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
src/settings/file-suggest.ts
Normal file
32
src/settings/file-suggest.ts
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { App, AbstractInputSuggest } from "obsidian";
|
||||||
|
|
||||||
|
export default class FileSuggest extends AbstractInputSuggest<string> {
|
||||||
|
private files: Array<string>;
|
||||||
|
private inputEl: HTMLInputElement;
|
||||||
|
|
||||||
|
constructor(app: App, inputEl: HTMLInputElement) {
|
||||||
|
super(app, inputEl);
|
||||||
|
|
||||||
|
this.inputEl = inputEl;
|
||||||
|
this.files = this.app.vault.getFiles().map((file) => file.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSuggestions(inputStr: string): string[] {
|
||||||
|
const inputLower = inputStr.toLowerCase();
|
||||||
|
|
||||||
|
return this.files.filter((file) =>
|
||||||
|
file.toLowerCase().includes(inputLower),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSuggestion(folder: string, el: HTMLElement): void {
|
||||||
|
el.setText(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectSuggestion(folder: string): void {
|
||||||
|
this.inputEl.value = folder;
|
||||||
|
const event = new Event("input");
|
||||||
|
this.inputEl.dispatchEvent(event);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,13 @@ export interface NodeFactorSettings {
|
||||||
bwdMultiplier: number;
|
bwdMultiplier: number;
|
||||||
|
|
||||||
lettersPerWt: number;
|
lettersPerWt: number;
|
||||||
|
|
||||||
|
manual: Array<FileData>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface FileData {
|
||||||
|
id: string;
|
||||||
|
weight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_SETTINGS: NodeFactorSettings = {
|
export const DEFAULT_SETTINGS: NodeFactorSettings = {
|
||||||
|
|
@ -21,4 +28,6 @@ export const DEFAULT_SETTINGS: NodeFactorSettings = {
|
||||||
bwdMultiplier: 1,
|
bwdMultiplier: 1,
|
||||||
|
|
||||||
lettersPerWt: 0,
|
lettersPerWt: 0,
|
||||||
|
|
||||||
|
manual: new Array<FileData>(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,22 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": "src",
|
||||||
"inlineSourceMap": true,
|
"inlineSourceMap": true,
|
||||||
"inlineSources": true,
|
"inlineSources": true,
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"target": "ES6",
|
"target": "ES6",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"noImplicitAny": true,
|
"noImplicitAny": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"importHelpers": true,
|
"importHelpers": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"strictNullChecks": true,
|
"strictNullChecks": true,
|
||||||
|
"strictBindCallApply": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"useUnknownInCatchVariables": true,
|
||||||
"lib": [
|
"lib": [
|
||||||
"DOM",
|
"DOM",
|
||||||
"ES5",
|
"ES5",
|
||||||
|
|
@ -19,6 +25,6 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"**/*.ts"
|
"src/**/*.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,15 @@ import { readFileSync, writeFileSync } from "fs";
|
||||||
const targetVersion = process.env.npm_package_version;
|
const targetVersion = process.env.npm_package_version;
|
||||||
|
|
||||||
// read minAppVersion from manifest.json and bump version to target version
|
// read minAppVersion from manifest.json and bump version to target version
|
||||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
const manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||||
const { minAppVersion } = manifest;
|
const { minAppVersion } = manifest;
|
||||||
manifest.version = targetVersion;
|
manifest.version = targetVersion;
|
||||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||||
|
|
||||||
// update versions.json with target version and minAppVersion from manifest.json
|
// update versions.json with target version and minAppVersion from manifest.json
|
||||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
// but only if the target version is not already in versions.json
|
||||||
versions[targetVersion] = minAppVersion;
|
const versions = JSON.parse(readFileSync('versions.json', 'utf8'));
|
||||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
if (!Object.values(versions).includes(minAppVersion)) {
|
||||||
|
versions[targetVersion] = minAppVersion;
|
||||||
|
writeFileSync('versions.json', JSON.stringify(versions, null, '\t'));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue