diff --git a/docs/Juggl.md b/docs/Juggl.md
index 223a9db..2a1f698 100644
--- a/docs/Juggl.md
+++ b/docs/Juggl.md
@@ -9,7 +9,6 @@ Juggl is the next generation of PKM-focused graph views!
- **Code** is on Github: https://github.com/HEmile/juggl
- **Support the development** of Juggl:
- Buy me a kofi: https://ko-fi.com/Emile
- - Sponsor me on Github: https://github.com/sponsors/HEmile
- Paypal.me: https://paypal.me/EvanKrieken
# Features
@@ -51,6 +50,8 @@ Note that Juggl is GPL3 **dual-**licensed. Contact me for details.
# Neo4j Graph View
If you came here looking for the documentation of the deprecated [[Neo4j Graph View Plugin]], please go [[Neo4j Graph View Plugin|here]].
+
+
---
#plugin
- author [[Emile van Krieken]]
diff --git a/juggl/main.ts b/juggl/main.ts
index aa4a077..4682728 100644
--- a/juggl/main.ts
+++ b/juggl/main.ts
@@ -9,20 +9,17 @@ import {
DefaultJugglSettings, LAYOUTS,
genStyleGroups, emptyStyleGroup,
} from './settings';
-import {Juggl, MD_VIEW_TYPE} from './viz/visualization';
+import {Juggl} from './viz/visualization';
import {ImageServer} from './image-server';
import type {
ICoreDataStore,
IDataStore,
IJugglStores,
- ITypedLink,
- ITypedLinkProperties,
IJugglPlugin,
IJuggl,
} from 'juggl-api';
import {OBSIDIAN_STORE_NAME, ObsidianStore} from './obsidian-store';
import cytoscape, {NodeSingular} from 'cytoscape';
-// import coseBilkent from 'cytoscape-cose-bilkent';
import navigator from 'cytoscape-navigator';
import popper from 'cytoscape-popper';
import cola from 'cytoscape-cola';
@@ -50,9 +47,7 @@ import {GlobalWarningModal} from './ui/settings/global-graph-modal';
export default class JugglPlugin extends Plugin implements IJugglPlugin {
// Match around [[ and ]], and ensure content isn't a wikilnk closure
// This doesn't explicitly parse aliases.
- static wikilinkRegex = '\\[\\[([^\\]\\r\\n]+?)\\]\\]';//
static CAT_DANGLING = 'dangling';
- static nameRegex = '[^\\W\\d]\\w*';
settings: IJugglPluginSettings;
path: string;
@@ -294,6 +289,7 @@ export default class JugglPlugin extends Plugin implements IJugglPlugin {
this.setGlobalIcon();
this.addChild(new ImageServer(this));
}
+
public setGlobalIcon() {
if (this.ribbonIcon) {
this.ribbonIcon.detach();
@@ -304,6 +300,7 @@ export default class JugglPlugin extends Plugin implements IJugglPlugin {
});
}
}
+
public async openFileFromNode(node: NodeSingular, newLeaf= false): Promise {
const id = VizId.fromNode(node);
if (!(id.storeId === 'core')) {
@@ -361,114 +358,6 @@ export default class JugglPlugin extends Plugin implements IJugglPlugin {
// '"}) OPTIONAL MATCH (n)-[r]-(m) RETURN n,r,m';
// }
- _parseTags(tags: string[]): string[] {
- return [].concat(...tags
- .map((tag) => {
- tag = tag.slice(1);
- const hSplit = tag.split('/');
- const tags = [];
- for (const i in hSplit) {
- const hTag = hSplit.slice(0, parseInt(i) + 1).join('-');
- tags.push(`tag-${hTag}`);
- }
- return tags;
- }));
- }
-
- public getClasses(file: TFile): string[] {
- if (file) {
- const classes = [];
- if (['png', 'jpg', 'jpeg', 'gif', 'bmp', 'svg', 'tiff'].contains(file.extension)) {
- classes.push('image');
- } else if (['mp3', 'webm', 'wav', 'm4a', 'ogg', '3gp', 'flac'].contains(file.extension)) {
- classes.push('audio');
- } else if (['mp4', 'webm', 'ogv'].contains(file.extension)) {
- classes.push('video');
- } else if (file.extension === 'pdf') {
- classes.push('pdf');
- }
- // This is replaced by the 'path' data attribute.
- // if (!(file.parent.name === '/' || file.parent.name === '')) {
- // classes.push(`folder-${file.parent.name
- // .replace(' ', '_')}`);
- // } else {
- // classes.push('root');
- // }
- if (file.extension === 'md') {
- classes.push('note');
- const cache = this.app.metadataCache.getFileCache(file);
- if (cache?.frontmatter) {
- if ('image' in cache.frontmatter) {
- classes.push('image');
- }
- if ('tags' in cache.frontmatter) {
- const tags = parseFrontMatterTags(cache.frontmatter);
- if (tags) {
- classes.push(...this._parseTags(tags));
- }
- }
- if ('cssclass' in cache.frontmatter) {
- const clazzes = parseFrontMatterStringArray(cache.frontmatter, 'cssclass');
- if (clazzes) {
- classes.push(...clazzes);
- }
- }
- }
- if (cache?.tags) {
- classes.push(...this._parseTags(cache.tags.map((t) => t.tag)));
- }
- } else {
- classes.push('file');
- }
- return classes;
- }
- return [JugglPlugin.CAT_DANGLING];
- }
-
- regexEscape(str: string) {
- return str.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
- }
-
- public parseTypedLink(link: ReferenceCache, line: string): ITypedLink {
- // TODO: This is something specific I use, but shouldn't keep being in this repo.
- const regexPublishedIn = new RegExp(
- `^${this.regexEscape(this.settings.typedLinkPrefix)} (publishedIn) (\\d\\d\\d\\d) (${JugglPlugin.wikilinkRegex},? *)+$`);
- const matchPI = regexPublishedIn.exec(line);
- if (!(matchPI === null)) {
- return {
- class: 'type-publishedIn',
- isInline: false,
- properties: {
- year: matchPI[2],
- context: '',
- type: 'publishedIn',
- } as ITypedLinkProperties,
- } as ITypedLink;
- }
-
- // Intuition: Start with the typed link prefix. Then a neo4j name (nameRegex).
- // Then one or more of the wikilink group: wikilink regex separated by optional comma and multiple spaces
- const regex = new RegExp(
- `^${this.regexEscape(this.settings.typedLinkPrefix)} (${JugglPlugin.nameRegex}) (${JugglPlugin.wikilinkRegex},? *)+$`);
- const match = regex.exec(line);
- const splitLink = link.original.split('|');
- let alias = null;
- if (splitLink.length > 1) {
- alias = splitLink.slice(1).join().slice(0, -2);
- }
- if (!(match === null)) {
- return {
- class: `type-${match[1]}`,
- isInline: false,
- properties: {
- alias: alias,
- context: '',
- type: match[1],
- } as ITypedLinkProperties,
- } as ITypedLink;
- }
- return null;
- }
// executeQuery() {
// // Code taken from https://github.com/mrjackphil/obsidian-text-expand/blob/0.6.4/main.ts
diff --git a/juggl/obsidian-store.ts b/juggl/obsidian-store.ts
index 0490ee9..1f3dbce 100644
--- a/juggl/obsidian-store.ts
+++ b/juggl/obsidian-store.ts
@@ -12,12 +12,10 @@ import type JugglPlugin from './main';
import type {
NodeDefinition,
EdgeDefinition,
- NodeDataDefinition,
NodeCollection,
- EdgeDataDefinition, Collection,
} from 'cytoscape';
import {CLASS_EXPANDED} from './constants';
-import {VizId} from 'juggl-api';
+import {nodeDangling, nodeFromFile, parseRefCache, VizId} from 'juggl-api';
export const OBSIDIAN_STORE_NAME = 'Obsidian';
@@ -54,31 +52,7 @@ export class ObsidianStore extends Component implements ICoreDataStore {
if (toNodes.$id(otherId).length > 0) {
const edgeId = `${srcId}->${otherId}`;
const count = edgeId in edges ? edges[edgeId].length + 1 : 1;
- const line = content[ref.position.start.line];
- let data = {
- id: `${edgeId}${count}`,
- source: srcId,
- target: otherId,
- context: line,
- edgeCount: 1,
- } as EdgeDataDefinition;
- const splitLink = ref.original.split('|');
- if (splitLink.length > 1) {
- data['alias'] = splitLink.slice(1).join().slice(0, -2);
- }
- let classes = '';
- const typedLink = this.plugin.parseTypedLink(ref, line);
- if (typedLink === null) {
- classes = `${classes} inline`;
- } else {
- data = {...typedLink.properties, ...data};
- classes = `${classes} ${typedLink.class}`;
- }
- const edge = {
- group: 'edges',
- data: data,
- classes: classes,
- } as EdgeDefinition;
+ const edge = parseRefCache(ref, content, `${edgeId}${count}`, srcId, otherId, this.plugin.settings.typedLinkPrefix);
if (edgeId in edges) {
edges[edgeId].push(edge);
} else {
@@ -166,9 +140,9 @@ ${edge.data.context}`;
const path = getLinkpath(link.link);
const file = this.metadata.getFirstLinkpathDest(path, sourcePath);
if (file) {
- return await this.nodeFromFile(file);
+ return await nodeFromFile(file, this.plugin);
} else {
- return this.nodeDangling(path);
+ return nodeDangling(path);
}
}
@@ -187,61 +161,13 @@ ${edge.data.context}`;
const file = this.vault.getAbstractFileByPath(otherPath) as TFile;
const id = VizId.fromFile(file).toId();
if (!(id in nodes)) {
- nodes[id] = await this.nodeFromFile(file);
+ nodes[id] = await nodeFromFile(file, this.plugin);
}
}
}
}
}
- async nodeFromFile(file: TFile) : Promise {
- const cache = this.metadata.getFileCache(file);
- const name = file.extension === 'md' ? file.basename : file.name;
- const classes = this.plugin.getClasses(file).join(' ');
- const data = {
- id: VizId.toId(file.name, this.storeId()),
- name: name,
- path: file.path,
- resource_url: `http://localhost:${this.plugin.settings.imgServerPort}/${encodeURI(file.path)}`,
- } as NodeDataDefinition;
- data['content'] = await this.vault.cachedRead(file);
- const frontmatter = cache?.frontmatter;
- if (frontmatter) {
- Object.keys(frontmatter).forEach((k) => {
- if (!(k === 'position')) {
- if (k === 'image') {
- const imageField = frontmatter[k];
- try {
- // Check if url. throws error otherwise
- new URL(imageField);
- data[k] = imageField;
- } catch {
- data[k] = `http://localhost:${this.plugin.settings.imgServerPort}/${encodeURI(imageField)}`;
- }
- } else {
- data[k] = frontmatter[k];
- }
- }
- });
- }
-
- return {
- group: 'nodes',
- data: data,
- classes: classes,
- };
- }
-
- nodeDangling(path: string): NodeDefinition {
- return {
- group: 'nodes',
- data: {
- id: VizId.toId(path, this.storeId()),
- name: path,
- },
- classes: 'dangling',
- };
- }
async getNeighbourhood(nodeIds: VizId[]): Promise {
const nodes: Record = {};
@@ -256,7 +182,7 @@ ${edge.data.context}`;
continue;
}
if (!(nodeId.toId() in nodes)) {
- nodes[nodeId.toId()] = await this.nodeFromFile(file);
+ nodes[nodeId.toId()] = await nodeFromFile(file, this.plugin);
}
const promiseNodes: Record> = {};
iterateCacheRefs(cache, (ref) => {
@@ -290,7 +216,7 @@ ${edge.data.context}`;
console.log('returning empty cache', nodeId);
return null;
}
- return Promise.resolve(this.nodeFromFile(file));
+ return Promise.resolve(nodeFromFile(file, this.plugin));
}
async refreshNode(view: IJuggl, id: VizId) {
diff --git a/juggl/package-lock.json b/juggl/package-lock.json
index f1770eb..1790b86 100644
--- a/juggl/package-lock.json
+++ b/juggl/package-lock.json
@@ -18,7 +18,7 @@
"cytoscape-dblclick": "^0.3.1",
"cytoscape-navigator": "^2.0.1",
"cytoscape-popper": "^2.0.0",
- "juggl-api": "github:hemile/juggl-api",
+ "juggl-api": "github:HEmile/juggl-api",
"obsidian": "github:obsidianmd/obsidian-api",
"search-query-parser": "^1.5.5"
},
@@ -2276,7 +2276,7 @@
},
"node_modules/juggl-api": {
"version": "1.0.0",
- "resolved": "git+ssh://git@github.com/hemile/juggl-api.git#7c9e0b0937d9e3119b36a800c8e34c9e3f4e81ce",
+ "resolved": "git+ssh://git@github.com/HEmile/juggl-api.git#f7d07e8a93788a0478dc4ef36c6d1394ce2f49a0",
"dependencies": {
"@types/cytoscape": "^3.14.11"
}
@@ -2519,7 +2519,7 @@
},
"node_modules/obsidian": {
"version": "0.12.0",
- "resolved": "git+ssh://git@github.com/obsidianmd/obsidian-api.git#ffc713b80981abb444b0e1ed21f2a870a3e15610",
+ "resolved": "git+ssh://git@github.com/obsidianmd/obsidian-api.git#068ff3052f0641baff90856dcb420dc2721680c9",
"license": "MIT",
"dependencies": {
"@types/codemirror": "0.0.108",
@@ -5242,8 +5242,8 @@
}
},
"juggl-api": {
- "version": "git+ssh://git@github.com/hemile/juggl-api.git#7c9e0b0937d9e3119b36a800c8e34c9e3f4e81ce",
- "from": "juggl-api@github:hemile/juggl-api",
+ "version": "git+ssh://git@github.com/HEmile/juggl-api.git#f7d07e8a93788a0478dc4ef36c6d1394ce2f49a0",
+ "from": "juggl-api@github:HEmile/juggl-api",
"requires": {
"@types/cytoscape": "^3.14.11"
}
@@ -5436,7 +5436,7 @@
}
},
"obsidian": {
- "version": "git+ssh://git@github.com/obsidianmd/obsidian-api.git#ffc713b80981abb444b0e1ed21f2a870a3e15610",
+ "version": "git+ssh://git@github.com/obsidianmd/obsidian-api.git#068ff3052f0641baff90856dcb420dc2721680c9",
"from": "obsidian@github:obsidianmd/obsidian-api",
"requires": {
"@types/codemirror": "0.0.108",
diff --git a/juggl/package.json b/juggl/package.json
index 73f674a..4b2d952 100644
--- a/juggl/package.json
+++ b/juggl/package.json
@@ -58,7 +58,7 @@
"cytoscape-dblclick": "^0.3.1",
"cytoscape-navigator": "^2.0.1",
"cytoscape-popper": "^2.0.0",
- "juggl-api": "github:hemile/juggl-api",
+ "juggl-api": "github:HEmile/juggl-api",
"obsidian": "github:obsidianmd/obsidian-api",
"search-query-parser": "^1.5.5"
}
diff --git a/manifest.json b/manifest.json
index 5f8c13a..cbd33bc 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"id": "juggl",
"name": "Juggl",
- "version": "1.1.0",
+ "version": "1.1.1",
"minAppVersion": "0.11.5",
"description": "Adds a completely interactive, stylable and expandable graph view to Obsidian.",
"author": "Emile",