@zoldia/omnigraph 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -94
- package/dist/cli.js +396 -1
- package/package.json +12 -3
- package/ui/assets/index-B4R9LC7F.js +23 -0
- package/ui/gif.worker.js +3 -0
- package/ui/index.html +1 -1
- package/ui/assets/index-DKa11qnN.js +0 -11
package/dist/cli.js
CHANGED
|
@@ -259851,6 +259851,89 @@ var require_typescript_parser = __commonJS({
|
|
|
259851
259851
|
}
|
|
259852
259852
|
return null;
|
|
259853
259853
|
}
|
|
259854
|
+
var NEXTJS_HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
259855
|
+
function detectNextJSAppRoute(filePath, exportedNames) {
|
|
259856
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
259857
|
+
const basename = path2.basename(normalized, path2.extname(normalized));
|
|
259858
|
+
if (basename !== "route")
|
|
259859
|
+
return null;
|
|
259860
|
+
const appMatch = normalized.match(/(?:^|\/)(src\/)?app\/(.*?)\/route\.\w+$/);
|
|
259861
|
+
if (!appMatch)
|
|
259862
|
+
return null;
|
|
259863
|
+
const routeDir = appMatch[2];
|
|
259864
|
+
const routePath = "/" + routeDir.split("/").map((segment) => {
|
|
259865
|
+
if (/^\[\[?\.\.\.\w+\]?\]$/.test(segment)) {
|
|
259866
|
+
const name = segment.replace(/[\[\]\.]/g, "");
|
|
259867
|
+
return `:${name}*`;
|
|
259868
|
+
}
|
|
259869
|
+
if (/^\[\w+\]$/.test(segment)) {
|
|
259870
|
+
return ":" + segment.slice(1, -1);
|
|
259871
|
+
}
|
|
259872
|
+
return segment;
|
|
259873
|
+
}).join("/");
|
|
259874
|
+
const methods = exportedNames.filter((n) => NEXTJS_HTTP_METHODS.includes(n));
|
|
259875
|
+
if (methods.length === 0) {
|
|
259876
|
+
return { nodeType: "nextjs-api-route", route: routePath };
|
|
259877
|
+
}
|
|
259878
|
+
const routeEntries = methods.map((m) => `${m} ${routePath}`).join(", ");
|
|
259879
|
+
return { nodeType: "nextjs-api-route", route: routeEntries };
|
|
259880
|
+
}
|
|
259881
|
+
function detectNextJSPagesApiRoute(filePath, hasDefaultExport) {
|
|
259882
|
+
if (!hasDefaultExport)
|
|
259883
|
+
return null;
|
|
259884
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
259885
|
+
const basename = path2.basename(normalized, path2.extname(normalized));
|
|
259886
|
+
const pagesMatch = normalized.match(/(?:^|\/)(src\/)?pages\/api\/(.*?)(\.\w+)$/);
|
|
259887
|
+
if (!pagesMatch)
|
|
259888
|
+
return null;
|
|
259889
|
+
let routeSegments = pagesMatch[2];
|
|
259890
|
+
if (basename === "index") {
|
|
259891
|
+
routeSegments = routeSegments.replace(/\/?index$/, "");
|
|
259892
|
+
}
|
|
259893
|
+
const segments = routeSegments.split("/").filter(Boolean).map((segment) => {
|
|
259894
|
+
if (/^\[\[?\.\.\.\w+\]?\]$/.test(segment)) {
|
|
259895
|
+
const name = segment.replace(/[\[\]\.]/g, "");
|
|
259896
|
+
return `:${name}*`;
|
|
259897
|
+
}
|
|
259898
|
+
if (/^\[\w+\]$/.test(segment)) {
|
|
259899
|
+
return ":" + segment.slice(1, -1);
|
|
259900
|
+
}
|
|
259901
|
+
return segment;
|
|
259902
|
+
});
|
|
259903
|
+
const routePath = segments.length > 0 ? "/api/" + segments.join("/") : "/api";
|
|
259904
|
+
return { nodeType: "nextjs-api-route", route: routePath };
|
|
259905
|
+
}
|
|
259906
|
+
function detectNextJSPage(filePath) {
|
|
259907
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
259908
|
+
const basename = path2.basename(normalized, path2.extname(normalized));
|
|
259909
|
+
if (basename !== "page")
|
|
259910
|
+
return null;
|
|
259911
|
+
const appMatch = normalized.match(/(?:^|\/)(src\/)?app\/(.*?)\/page\.\w+$/);
|
|
259912
|
+
if (!appMatch)
|
|
259913
|
+
return null;
|
|
259914
|
+
const routeDir = appMatch[2];
|
|
259915
|
+
const routePath = "/" + routeDir.split("/").map((segment) => {
|
|
259916
|
+
if (/^\[\[?\.\.\.\w+\]?\]$/.test(segment)) {
|
|
259917
|
+
const name = segment.replace(/[\[\]\.]/g, "");
|
|
259918
|
+
return `:${name}*`;
|
|
259919
|
+
}
|
|
259920
|
+
if (/^\[\w+\]$/.test(segment)) {
|
|
259921
|
+
return ":" + segment.slice(1, -1);
|
|
259922
|
+
}
|
|
259923
|
+
return segment;
|
|
259924
|
+
}).join("/");
|
|
259925
|
+
return { nodeType: "nextjs-page", route: routePath };
|
|
259926
|
+
}
|
|
259927
|
+
function detectNextJSLayout(filePath) {
|
|
259928
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
259929
|
+
const basename = path2.basename(normalized, path2.extname(normalized));
|
|
259930
|
+
if (basename !== "layout")
|
|
259931
|
+
return null;
|
|
259932
|
+
const appMatch = normalized.match(/(?:^|\/)(src\/)?app\/(.+\/)?layout\.\w+$/);
|
|
259933
|
+
if (!appMatch)
|
|
259934
|
+
return null;
|
|
259935
|
+
return { nodeType: "nextjs-layout", route: "" };
|
|
259936
|
+
}
|
|
259854
259937
|
var RESOLVE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx"];
|
|
259855
259938
|
function resolveImport(fromFile, importPath) {
|
|
259856
259939
|
const base = path2.normalize(path2.join(path2.dirname(fromFile), importPath));
|
|
@@ -259888,6 +259971,8 @@ var require_typescript_parser = __commonJS({
|
|
|
259888
259971
|
const isJS = /\.(js|jsx)$/.test(filePath);
|
|
259889
259972
|
let nodeType = isJS ? "javascript-file" : "typescript-file";
|
|
259890
259973
|
let route = "";
|
|
259974
|
+
const exportedNames = [];
|
|
259975
|
+
let hasDefaultExport = false;
|
|
259891
259976
|
for (const stmt of ast.body) {
|
|
259892
259977
|
if (stmt.type === "ImportDeclaration") {
|
|
259893
259978
|
const src = stmt.source.value;
|
|
@@ -259904,6 +259989,31 @@ var require_typescript_parser = __commonJS({
|
|
|
259904
259989
|
}
|
|
259905
259990
|
}
|
|
259906
259991
|
}
|
|
259992
|
+
if (stmt.type === "ExportNamedDeclaration") {
|
|
259993
|
+
if (stmt.declaration) {
|
|
259994
|
+
const decl = stmt.declaration;
|
|
259995
|
+
if (decl.type === "FunctionDeclaration" && decl.id && typeof decl.id.name === "string") {
|
|
259996
|
+
exportedNames.push(decl.id.name);
|
|
259997
|
+
}
|
|
259998
|
+
if (decl.type === "VariableDeclaration" && Array.isArray(decl.declarations)) {
|
|
259999
|
+
for (const d of decl.declarations) {
|
|
260000
|
+
if (d.id && typeof d.id.name === "string") {
|
|
260001
|
+
exportedNames.push(d.id.name);
|
|
260002
|
+
}
|
|
260003
|
+
}
|
|
260004
|
+
}
|
|
260005
|
+
}
|
|
260006
|
+
if (stmt.specifiers) {
|
|
260007
|
+
for (const spec of stmt.specifiers) {
|
|
260008
|
+
if (spec.exported && typeof spec.exported.name === "string") {
|
|
260009
|
+
exportedNames.push(spec.exported.name);
|
|
260010
|
+
}
|
|
260011
|
+
}
|
|
260012
|
+
}
|
|
260013
|
+
}
|
|
260014
|
+
if (stmt.type === "ExportDefaultDeclaration") {
|
|
260015
|
+
hasDefaultExport = true;
|
|
260016
|
+
}
|
|
259907
260017
|
let classNode = null;
|
|
259908
260018
|
if (stmt.type === "ExportNamedDeclaration" && stmt.declaration?.type === "ClassDeclaration") {
|
|
259909
260019
|
classNode = stmt.declaration;
|
|
@@ -259919,6 +260029,13 @@ var require_typescript_parser = __commonJS({
|
|
|
259919
260029
|
}
|
|
259920
260030
|
}
|
|
259921
260031
|
}
|
|
260032
|
+
if (nodeType === "typescript-file" || nodeType === "javascript-file") {
|
|
260033
|
+
const nextResult = detectNextJSAppRoute(filePath, exportedNames) ?? detectNextJSPagesApiRoute(filePath, hasDefaultExport) ?? detectNextJSPage(filePath) ?? detectNextJSLayout(filePath);
|
|
260034
|
+
if (nextResult) {
|
|
260035
|
+
nodeType = nextResult.nodeType;
|
|
260036
|
+
route = nextResult.route;
|
|
260037
|
+
}
|
|
260038
|
+
}
|
|
259922
260039
|
const node = {
|
|
259923
260040
|
id: fileId,
|
|
259924
260041
|
type: nodeType,
|
|
@@ -260433,6 +260550,281 @@ var require_php_parser = __commonJS({
|
|
|
260433
260550
|
}
|
|
260434
260551
|
});
|
|
260435
260552
|
|
|
260553
|
+
// packages/parsers/dist/markdown/markdown-parser.js
|
|
260554
|
+
var require_markdown_parser = __commonJS({
|
|
260555
|
+
"packages/parsers/dist/markdown/markdown-parser.js"(exports2) {
|
|
260556
|
+
"use strict";
|
|
260557
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? (function(o, m, k, k2) {
|
|
260558
|
+
if (k2 === void 0) k2 = k;
|
|
260559
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
260560
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
260561
|
+
desc = { enumerable: true, get: function() {
|
|
260562
|
+
return m[k];
|
|
260563
|
+
} };
|
|
260564
|
+
}
|
|
260565
|
+
Object.defineProperty(o, k2, desc);
|
|
260566
|
+
}) : (function(o, m, k, k2) {
|
|
260567
|
+
if (k2 === void 0) k2 = k;
|
|
260568
|
+
o[k2] = m[k];
|
|
260569
|
+
}));
|
|
260570
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? (function(o, v) {
|
|
260571
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
260572
|
+
}) : function(o, v) {
|
|
260573
|
+
o["default"] = v;
|
|
260574
|
+
});
|
|
260575
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ (function() {
|
|
260576
|
+
var ownKeys = function(o) {
|
|
260577
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
260578
|
+
var ar = [];
|
|
260579
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
260580
|
+
return ar;
|
|
260581
|
+
};
|
|
260582
|
+
return ownKeys(o);
|
|
260583
|
+
};
|
|
260584
|
+
return function(mod) {
|
|
260585
|
+
if (mod && mod.__esModule) return mod;
|
|
260586
|
+
var result = {};
|
|
260587
|
+
if (mod != null) {
|
|
260588
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
260589
|
+
}
|
|
260590
|
+
__setModuleDefault(result, mod);
|
|
260591
|
+
return result;
|
|
260592
|
+
};
|
|
260593
|
+
})();
|
|
260594
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
260595
|
+
exports2.MarkdownParser = void 0;
|
|
260596
|
+
var path2 = __importStar(require("path"));
|
|
260597
|
+
var fs = __importStar(require("fs"));
|
|
260598
|
+
var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
260599
|
+
var YAML_TAGS_INLINE = /^tags:\s*\[([^\]]*)\]/m;
|
|
260600
|
+
var YAML_TAGS_KEY = /^tags:\s*$/m;
|
|
260601
|
+
var YAML_ALIASES = /^aliases:\s*\[([^\]]*)\]/m;
|
|
260602
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".bmp"]);
|
|
260603
|
+
var MarkdownParser = class {
|
|
260604
|
+
constructor() {
|
|
260605
|
+
this.rootDir = "";
|
|
260606
|
+
}
|
|
260607
|
+
setRootDir(dir) {
|
|
260608
|
+
this.rootDir = dir;
|
|
260609
|
+
}
|
|
260610
|
+
canHandle(filePath) {
|
|
260611
|
+
const ext = path2.extname(filePath).toLowerCase();
|
|
260612
|
+
return ext === ".md" || ext === ".mdx";
|
|
260613
|
+
}
|
|
260614
|
+
parse(filePath, source) {
|
|
260615
|
+
const nodes = [];
|
|
260616
|
+
const edges = [];
|
|
260617
|
+
const fileId = filePath.replace(/\\/g, "/");
|
|
260618
|
+
const fileName = path2.basename(filePath, path2.extname(filePath));
|
|
260619
|
+
const frontmatter = this.parseFrontmatter(source);
|
|
260620
|
+
const headings = [];
|
|
260621
|
+
let headingMatch;
|
|
260622
|
+
const headingRegex = /^(#{1,6})\s+(.+)$/gm;
|
|
260623
|
+
while ((headingMatch = headingRegex.exec(source)) !== null) {
|
|
260624
|
+
headings.push(headingMatch[2].trim());
|
|
260625
|
+
}
|
|
260626
|
+
let nodeType = "markdown-file";
|
|
260627
|
+
if (frontmatter.tags.some((t) => t.toLowerCase() === "moc" || t.toLowerCase() === "index")) {
|
|
260628
|
+
nodeType = "markdown-moc";
|
|
260629
|
+
} else if (frontmatter.tags.some((t) => t.toLowerCase() === "daily" || t.toLowerCase() === "journal")) {
|
|
260630
|
+
nodeType = "markdown-daily";
|
|
260631
|
+
} else if (filePath.toLowerCase().includes("readme")) {
|
|
260632
|
+
nodeType = "markdown-readme";
|
|
260633
|
+
}
|
|
260634
|
+
const metadata = {
|
|
260635
|
+
filePath,
|
|
260636
|
+
language: "markdown"
|
|
260637
|
+
};
|
|
260638
|
+
if (headings.length > 0) {
|
|
260639
|
+
metadata.headings = headings.slice(0, 8).join(", ");
|
|
260640
|
+
}
|
|
260641
|
+
if (frontmatter.tags.length > 0) {
|
|
260642
|
+
metadata.tags = frontmatter.tags.join(", ");
|
|
260643
|
+
}
|
|
260644
|
+
if (frontmatter.aliases.length > 0) {
|
|
260645
|
+
metadata.aliases = frontmatter.aliases.join(", ");
|
|
260646
|
+
}
|
|
260647
|
+
nodes.push({
|
|
260648
|
+
id: fileId,
|
|
260649
|
+
type: nodeType,
|
|
260650
|
+
label: fileName,
|
|
260651
|
+
metadata
|
|
260652
|
+
});
|
|
260653
|
+
const body = this.stripFrontmatterAndCode(source);
|
|
260654
|
+
const linkedTargets = /* @__PURE__ */ new Set();
|
|
260655
|
+
let match;
|
|
260656
|
+
const wikiRegex = /\[\[([^\]|#]+)(?:#[^\]|]*)?\|?[^\]]*\]\]/g;
|
|
260657
|
+
while ((match = wikiRegex.exec(body)) !== null) {
|
|
260658
|
+
const target = match[1].trim();
|
|
260659
|
+
if (!target)
|
|
260660
|
+
continue;
|
|
260661
|
+
const ext = path2.extname(target).toLowerCase();
|
|
260662
|
+
if (IMAGE_EXTENSIONS.has(ext))
|
|
260663
|
+
continue;
|
|
260664
|
+
const resolved = this.resolveWikiLink(filePath, target);
|
|
260665
|
+
if (resolved && !linkedTargets.has(resolved)) {
|
|
260666
|
+
linkedTargets.add(resolved);
|
|
260667
|
+
edges.push({
|
|
260668
|
+
id: `e-${fileId}->${resolved}`,
|
|
260669
|
+
source: fileId,
|
|
260670
|
+
target: resolved,
|
|
260671
|
+
label: "links to"
|
|
260672
|
+
});
|
|
260673
|
+
}
|
|
260674
|
+
}
|
|
260675
|
+
const embedRegex = /!\[\[([^\]|#]+)(?:#[^\]|]*)?\|?[^\]]*\]\]/g;
|
|
260676
|
+
while ((match = embedRegex.exec(body)) !== null) {
|
|
260677
|
+
const target = match[1].trim();
|
|
260678
|
+
if (!target)
|
|
260679
|
+
continue;
|
|
260680
|
+
const ext = path2.extname(target).toLowerCase();
|
|
260681
|
+
if (IMAGE_EXTENSIONS.has(ext))
|
|
260682
|
+
continue;
|
|
260683
|
+
const resolved = this.resolveWikiLink(filePath, target);
|
|
260684
|
+
if (resolved && !linkedTargets.has(resolved)) {
|
|
260685
|
+
linkedTargets.add(resolved);
|
|
260686
|
+
edges.push({
|
|
260687
|
+
id: `e-${fileId}->embed-${resolved}`,
|
|
260688
|
+
source: fileId,
|
|
260689
|
+
target: resolved,
|
|
260690
|
+
label: "embeds"
|
|
260691
|
+
});
|
|
260692
|
+
}
|
|
260693
|
+
}
|
|
260694
|
+
const mdLinkRegex = /\[(?:[^\]]*)\]\((?!https?:\/\/|mailto:|#)([^)]+\.(?:md|mdx))\)/g;
|
|
260695
|
+
while ((match = mdLinkRegex.exec(body)) !== null) {
|
|
260696
|
+
const linkPath = match[1].trim();
|
|
260697
|
+
if (!linkPath)
|
|
260698
|
+
continue;
|
|
260699
|
+
const resolved = this.resolveRelativeLink(filePath, linkPath);
|
|
260700
|
+
if (resolved && !linkedTargets.has(resolved)) {
|
|
260701
|
+
linkedTargets.add(resolved);
|
|
260702
|
+
edges.push({
|
|
260703
|
+
id: `e-${fileId}->${resolved}`,
|
|
260704
|
+
source: fileId,
|
|
260705
|
+
target: resolved,
|
|
260706
|
+
label: "links to"
|
|
260707
|
+
});
|
|
260708
|
+
}
|
|
260709
|
+
}
|
|
260710
|
+
return { nodes, edges };
|
|
260711
|
+
}
|
|
260712
|
+
// ─── Frontmatter Parsing ─────────────────────────────────────────
|
|
260713
|
+
parseFrontmatter(source) {
|
|
260714
|
+
const tags = [];
|
|
260715
|
+
const aliases = [];
|
|
260716
|
+
const fmMatch = FRONTMATTER.exec(source);
|
|
260717
|
+
if (!fmMatch)
|
|
260718
|
+
return { tags, aliases };
|
|
260719
|
+
const fmBlock = fmMatch[1];
|
|
260720
|
+
const tagsInline = YAML_TAGS_INLINE.exec(fmBlock);
|
|
260721
|
+
if (tagsInline) {
|
|
260722
|
+
tags.push(...tagsInline[1].split(",").map((t) => t.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean));
|
|
260723
|
+
} else if (YAML_TAGS_KEY.test(fmBlock)) {
|
|
260724
|
+
let itemMatch;
|
|
260725
|
+
const itemRegex = /^\s+-\s+(.+)$/gm;
|
|
260726
|
+
const tagsSection = fmBlock.slice(fmBlock.indexOf("tags:"));
|
|
260727
|
+
while ((itemMatch = itemRegex.exec(tagsSection)) !== null) {
|
|
260728
|
+
tags.push(itemMatch[1].trim().replace(/^['"]|['"]$/g, ""));
|
|
260729
|
+
}
|
|
260730
|
+
}
|
|
260731
|
+
const aliasMatch = YAML_ALIASES.exec(fmBlock);
|
|
260732
|
+
if (aliasMatch) {
|
|
260733
|
+
aliases.push(...aliasMatch[1].split(",").map((a) => a.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean));
|
|
260734
|
+
}
|
|
260735
|
+
return { tags, aliases };
|
|
260736
|
+
}
|
|
260737
|
+
// ─── Link Resolution ─────────────────────────────────────────────
|
|
260738
|
+
/**
|
|
260739
|
+
* Resolve an Obsidian wiki-link target to a file path.
|
|
260740
|
+
* Obsidian uses "shortest path when possible" — [[Page]] matches
|
|
260741
|
+
* any file named Page.md anywhere in the vault.
|
|
260742
|
+
*/
|
|
260743
|
+
resolveWikiLink(fromFile, target) {
|
|
260744
|
+
const dir = path2.dirname(fromFile);
|
|
260745
|
+
if (path2.extname(target)) {
|
|
260746
|
+
return this.tryResolve(dir, target);
|
|
260747
|
+
}
|
|
260748
|
+
const resolved = this.tryResolve(dir, target + ".md") ?? this.tryResolve(dir, target + ".mdx");
|
|
260749
|
+
if (resolved)
|
|
260750
|
+
return resolved;
|
|
260751
|
+
if (this.rootDir) {
|
|
260752
|
+
const found = this.findFileInVault(target);
|
|
260753
|
+
if (found)
|
|
260754
|
+
return found;
|
|
260755
|
+
}
|
|
260756
|
+
return null;
|
|
260757
|
+
}
|
|
260758
|
+
/** Resolve a standard relative markdown link */
|
|
260759
|
+
resolveRelativeLink(fromFile, linkPath) {
|
|
260760
|
+
const dir = path2.dirname(fromFile);
|
|
260761
|
+
const candidate = path2.resolve(dir, linkPath);
|
|
260762
|
+
if (fs.existsSync(candidate)) {
|
|
260763
|
+
return candidate.replace(/\\/g, "/");
|
|
260764
|
+
}
|
|
260765
|
+
return null;
|
|
260766
|
+
}
|
|
260767
|
+
/** Try resolving a path relative to the current directory or as absolute */
|
|
260768
|
+
tryResolve(dir, target) {
|
|
260769
|
+
const relative = path2.resolve(dir, target);
|
|
260770
|
+
if (fs.existsSync(relative)) {
|
|
260771
|
+
return relative.replace(/\\/g, "/");
|
|
260772
|
+
}
|
|
260773
|
+
if (this.rootDir) {
|
|
260774
|
+
const fromRoot = path2.resolve(this.rootDir, target);
|
|
260775
|
+
if (fs.existsSync(fromRoot)) {
|
|
260776
|
+
return fromRoot.replace(/\\/g, "/");
|
|
260777
|
+
}
|
|
260778
|
+
}
|
|
260779
|
+
return null;
|
|
260780
|
+
}
|
|
260781
|
+
/**
|
|
260782
|
+
* Search the vault (rootDir) recursively for a file matching the target name.
|
|
260783
|
+
* This implements Obsidian's "shortest path" resolution for [[Page]] links.
|
|
260784
|
+
*/
|
|
260785
|
+
findFileInVault(target) {
|
|
260786
|
+
if (!this.rootDir)
|
|
260787
|
+
return null;
|
|
260788
|
+
const targetLower = target.toLowerCase();
|
|
260789
|
+
const extensions = [".md", ".mdx"];
|
|
260790
|
+
const queue = [this.rootDir];
|
|
260791
|
+
const skip = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".next", "build", ".obsidian"]);
|
|
260792
|
+
while (queue.length > 0) {
|
|
260793
|
+
const dir = queue.shift();
|
|
260794
|
+
let entries;
|
|
260795
|
+
try {
|
|
260796
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
260797
|
+
} catch {
|
|
260798
|
+
continue;
|
|
260799
|
+
}
|
|
260800
|
+
for (const entry of entries) {
|
|
260801
|
+
if (entry.isDirectory()) {
|
|
260802
|
+
if (!skip.has(entry.name)) {
|
|
260803
|
+
queue.push(path2.join(dir, entry.name));
|
|
260804
|
+
}
|
|
260805
|
+
} else if (entry.isFile()) {
|
|
260806
|
+
const name = path2.basename(entry.name, path2.extname(entry.name));
|
|
260807
|
+
const ext = path2.extname(entry.name).toLowerCase();
|
|
260808
|
+
if (name.toLowerCase() === targetLower && extensions.includes(ext)) {
|
|
260809
|
+
return path2.join(dir, entry.name).replace(/\\/g, "/");
|
|
260810
|
+
}
|
|
260811
|
+
}
|
|
260812
|
+
}
|
|
260813
|
+
}
|
|
260814
|
+
return null;
|
|
260815
|
+
}
|
|
260816
|
+
/** Strip frontmatter and fenced code blocks so link regexes don't match inside them */
|
|
260817
|
+
stripFrontmatterAndCode(source) {
|
|
260818
|
+
let body = source.replace(FRONTMATTER, "");
|
|
260819
|
+
body = body.replace(/```[\s\S]*?```/g, "");
|
|
260820
|
+
body = body.replace(/`[^`]*`/g, "");
|
|
260821
|
+
return body;
|
|
260822
|
+
}
|
|
260823
|
+
};
|
|
260824
|
+
exports2.MarkdownParser = MarkdownParser;
|
|
260825
|
+
}
|
|
260826
|
+
});
|
|
260827
|
+
|
|
260436
260828
|
// packages/parsers/dist/cross-network/http-call-detector.js
|
|
260437
260829
|
var require_http_call_detector = __commonJS({
|
|
260438
260830
|
"packages/parsers/dist/cross-network/http-call-detector.js"(exports2) {
|
|
@@ -260795,13 +261187,15 @@ var require_parser_registry = __commonJS({
|
|
|
260795
261187
|
var typescript_parser_1 = require_typescript_parser();
|
|
260796
261188
|
var python_parser_1 = require_python_parser();
|
|
260797
261189
|
var php_parser_1 = require_php_parser();
|
|
261190
|
+
var markdown_parser_1 = require_markdown_parser();
|
|
260798
261191
|
var cross_network_1 = require_cross_network();
|
|
260799
261192
|
var fs = __importStar(require("fs"));
|
|
260800
261193
|
var path2 = __importStar(require("path"));
|
|
260801
261194
|
var ignore_1 = __importDefault(require_ignore());
|
|
260802
261195
|
var pythonParser = new python_parser_1.PythonParser();
|
|
260803
261196
|
var phpParser = new php_parser_1.PhpParser();
|
|
260804
|
-
var
|
|
261197
|
+
var markdownParser = new markdown_parser_1.MarkdownParser();
|
|
261198
|
+
var parsers = [new typescript_parser_1.TypeScriptParser(), pythonParser, phpParser, markdownParser];
|
|
260805
261199
|
var ALWAYS_SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", ".next", "build"]);
|
|
260806
261200
|
function loadGitignore(rootDir) {
|
|
260807
261201
|
const ig = (0, ignore_1.default)();
|
|
@@ -260820,6 +261214,7 @@ var require_parser_registry = __commonJS({
|
|
|
260820
261214
|
const sourceByFileId = /* @__PURE__ */ new Map();
|
|
260821
261215
|
pythonParser.setRootDir(dirPath);
|
|
260822
261216
|
phpParser.setRootDir(dirPath);
|
|
261217
|
+
markdownParser.setRootDir(dirPath);
|
|
260823
261218
|
function walk(dir) {
|
|
260824
261219
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
260825
261220
|
for (const entry of entries) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zoldia/omnigraph",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "A multi-language, AST-driven dependency visualizer for complex codebases. Parses TypeScript/NestJS, Python/FastAPI/Django,
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "A multi-language, AST-driven dependency visualizer for complex codebases. Parses TypeScript/NestJS/Next.js, Python/FastAPI/Django, PHP/Laravel, and Markdown/Obsidian and renders an interactive dependency graph.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"omnigraph": "dist/cli.js"
|
|
7
7
|
},
|
|
@@ -19,12 +19,21 @@
|
|
|
19
19
|
"typescript",
|
|
20
20
|
"python",
|
|
21
21
|
"php",
|
|
22
|
+
"markdown",
|
|
22
23
|
"nestjs",
|
|
24
|
+
"nextjs",
|
|
23
25
|
"fastapi",
|
|
24
26
|
"django",
|
|
25
27
|
"laravel",
|
|
28
|
+
"obsidian",
|
|
29
|
+
"wiki-links",
|
|
26
30
|
"react-flow",
|
|
27
|
-
"
|
|
31
|
+
"gif-export",
|
|
32
|
+
"erd",
|
|
33
|
+
"foreign-keys",
|
|
34
|
+
"cli",
|
|
35
|
+
"method-extraction",
|
|
36
|
+
"tsconfig-paths"
|
|
28
37
|
],
|
|
29
38
|
"repository": {
|
|
30
39
|
"type": "git",
|