Open ccchan234 opened 1 year ago
rich1 rich2 rich1 as source, rich2 as target -> richr
rich1's json tree, for reference: Enter the name of the file to read: rich1.md YAML Front Matter:
mindmap-plugin: rich
Parsed JSON Block:
{ "theme": "", "mindData": [ [ { "id": "f2cbb51d-be9e-5909", "text": "111", "isExpand": true, "isRoot": true, "useScale": true, "useHandMode": false, "x": 3940, "y": 3800, "main": true, "layout": { "layoutName": "mindmap2", "direct": "mindmap" }, "stroke": "" }, { "id": "41457844-5c49-418d", "text": "123", "stroke": "#6ed3ea", "x": 4058, "y": 3779, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "86601dce-6d29-312c", "text": "345", "stroke": "#acdb48", "x": 4058, "y": 3840, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "8f1d1c02-0b0c-7add", "text": "567", "stroke": "#f0c2f9", "x": 3847, "y": 3810, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" } ] ], "induceData": [], "wireFrameData": [], "relateLinkData": [], "calloutData": [] }
JSON Block Details:
rich2: Enter the name of the file to read: rich2.md YAML Front Matter:
mindmap-plugin: rich
Parsed JSON Block:
{ "theme": "", "mindData": [ [ { "id": "f2cbb51d-be9e-5909", "text": "bbb", "isExpand": true, "isRoot": true, "useScale": true, "useHandMode": false, "x": 3940, "y": 3800, "main": true, "layout": { "layoutName": "mindmap2", "direct": "mindmap" }, "stroke": "" }, { "id": "7d9a6445-96e6-ab1f", "text": "abc", "stroke": "#6ed3ea", "x": 4065, "y": 3779, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "f6f65024-6e6b-08b8", "text": "def", "stroke": "#acdb48", "x": 4065, "y": 3840, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "0e395d2b-ae71-6342", "text": "ght", "stroke": "#f0c2f9", "x": 3854, "y": 3810, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" } ] ], "induceData": [], "wireFrameData": [], "relateLinkData": [], "calloutData": [] }
JSON Block Details:
Enter the name of the file to read: richr.md YAML Front Matter:
mindmap-plugin: rich
Parsed JSON Block:
{ "theme": "", "mindData": [ [ { "id": "f2cbb51d-be9e-5909", "text": "bbb", "isExpand": true, "isRoot": true, "useScale": true, "useHandMode": false, "x": 3940, "y": 3800, "main": true, "layout": { "layoutName": "mindmap2", "direct": "mindmap" }, "stroke": "" }, { "id": "7d9a6445-96e6-ab1f", "text": "abc", "stroke": "#6ed3ea", "x": 4065, "y": 3779, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "f6f65024-6e6b-08b8", "text": "def", "stroke": "#acdb48", "x": 4065, "y": 3840, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "0e395d2b-ae71-6342", "text": "ght", "stroke": "#f0c2f9", "x": 3854, "y": 3810, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "f2cbb51d-be9e-5909", "text": "111", "isExpand": true, "isRoot": true, "useScale": true, "useHandMode": false, "x": 3940, "y": 3800, "main": true, "layout": { "layoutName": "mindmap2", "direct": "mindmap" }, "stroke": "" }, { "id": "41457844-5c49-418d", "text": "123", "stroke": "#6ed3ea", "x": 4058, "y": 3779, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "86601dce-6d29-312c", "text": "345", "stroke": "#acdb48", "x": 4058, "y": 3840, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" }, { "id": "8f1d1c02-0b0c-7add", "text": "567", "stroke": "#f0c2f9", "x": 3847, "y": 3810, "layout": null, "isExpand": true, "pid": "f2cbb51d-be9e-5909" } ] ], "induceData": [], "wireFrameData": [], "relateLinkData": [], "calloutData": [] }
JSON Block Details:
me: i wanna introduce this script to my friend, can you simply explain how it work? gpt: Certainly! This script is a Node.js program designed to merge two mind map files in Markdown format. The mind map data is stored in a JSON block within the Markdown files. The script reads the JSON blocks from the source and target files, combines the mind maps (by adding nodes from the source to the target), and saves the updated JSON block back to the target file.
Here's a step-by-step explanation of how the script works:
Import the required modules: fs
(for file system operations), path
(to handle file paths), and readline-sync
(to read user input).
Define the readJSONBlock
function, which reads a file and extracts the JSON block from it. This function takes a file path as input and a callback function that will be called with the parsed JSON object.
Define the updateMindmap
function, which takes two JSON objects (target and source) as input. This function iterates through the nodes in the source mind map and adds them to the target mind map, if they don't already exist.
Use readline-sync
to prompt the user for the source and target file names.
Form the full file paths using the path
module.
Call the readJSONBlock
function for the source file to get the source JSON object.
Call the readJSONBlock
function for the target file to get the target JSON object.
Use the updateMindmap
function to merge the source and target JSON objects, creating an updated target JSON object.
Read the target file content using the fs
module.
Replace the original JSON block in the target file content with the updated JSON block.
Write the updated target file content back to the target file using the fs
module.
If everything is successful, print a message to the console indicating that the target file has been updated.
me: can you explain more about how the maps are compared, and what criterias are used to determine identical/different node?
gpt:
Sure! The script compares the nodes in the source and target mind maps based on three properties: id
, pid
, and text
. The comparison is performed in the updateMindmap
function. Here's a more detailed explanation of the comparison process:
Iterate through each node in the source mind map using a for
loop.
For each source node, the script checks if there is any node in the target mind map that matches all three properties (id
, pid
, and text
). This check is performed using the Array.prototype.some()
method, which tests whether at least one element in the array passes the provided test function.
The test function inside some()
compares the id
, pid
, and text
properties of the target node with the corresponding properties of the source node. If all three properties match, the test function returns true
, indicating that an identical node was found in the target mind map.
target.mindData[0].some(tNode => tNode.id === node.id && tNode.pid === node.pid && tNode.text === node.text)
If an identical node is found in the target mind map (some()
returns true
), the script skips the current source node and continues with the next one.
If no identical node is found in the target mind map (some()
returns false
), the script adds the current source node to the target mind map.
target.mindData[0].push(node);
After iterating through all the nodes in the source mind map, the updated target JSON object is returned.
In summary, two nodes are considered identical if their id
, pid
, and text
properties match. If a source node is not found in the target mind map (based on these criteria), it is added to the target mind map.
what i think the future use is, made into a ctrlP function.
then the user 's current active document is targer.md, use ctrlP then will ask use which file as source.md and update the target.md
pls advise thx
just download, rename as .js, then run with node.js
gpt made it into a typescript, but i cant build it. there is something wrong with my npm/ts compiler.
import { Plugin, TFile } from 'obsidian'; import { readFile, writeFile } from 'fs/promises';
export default class MindmapMergerPlugin extends Plugin { async onload() { this.addCommand({ id: 'merge-mindmaps', name: 'Merge Mindmaps', checkCallback: (checking: boolean) => { if (!checking) { this.mergeMindmaps(); } return true; }, }); }
async mergeMindmaps() { const targetFile = this.app.workspace.getActiveFile(); if (!targetFile) { new Notice('No active file found. Please open the target file.'); return; }
const sourceFile = await this.app.fileManager.getFileChooser().choose();
if (!sourceFile) {
new Notice('No source file selected. Aborting merge process.');
return;
}
new Notice(`Merging ${sourceFile.basename} into ${targetFile.basename}.`);
const targetJson = await this.extractJsonFromMarkdownFile(targetFile);
const sourceJson = await this.extractJsonFromMarkdownFile(sourceFile);
const updatedTargetJson = this.updateMindmap(targetJson, sourceJson);
const targetContent = await this.app.vault.read(targetFile);
const updatedTargetContent = this.updateTargetFileContent(targetContent, updatedTargetJson);
await this.app.vault.modify(targetFile, updatedTargetContent);
new Notice('Merge process finished. The target file has been updated.');
}
async extractJsonFromMarkdownFile(file: TFile) { const fileContent = await this.app.vault.read(file); const jsonStart = fileContent.indexOf('{'); const jsonEnd = fileContent.lastIndexOf('}') + 1; const jsonBlock = JSON.parse(fileContent.substring(jsonStart, jsonEnd)); return jsonBlock; }
updateMindmap(target: any, source: any) { for (const node of source.mindData[0]) { if (!target.mindData[0].some(tNode => tNode.id === node.id && tNode.pid === node.pid && tNode.text === node.text)) { target.mindData[0].push(node); } } return target; }
updateTargetFileContent(fileContent: string, updatedJson: any) { const jsonStart = fileContent.indexOf('{'); const jsonEnd = fileContent.lastIndexOf('}') + 1; const updatedJsonBlock = JSON.stringify(updatedJson, null, 2); const updatedFileContent = fileContent.substring(0, jsonStart) + updatedJsonBlock + fileContent.substring(jsonEnd); return updatedFileContent; } }
the compiling is always hard to me. i give up.
runing that as .js is ok.
v042, MNR.js, just dnld as .js, rune /w node of node.js
`const fs = require('fs'); const path = require('path'); const readlineSync = require('readline-sync');
const readJSONBlock = (filePath, callback) => { fs.readFile(filePath, 'utf-8', (err, data) => { if (err) { callback(err); return; }
const jsonStart = data.indexOf('{');
const jsonEnd = data.lastIndexOf('}') + 1;
const jsonBlock = JSON.parse(data.substring(jsonStart, jsonEnd));
callback(null, jsonBlock);
}); };
const updateMindmap = (target, source) => { for (const node of source.mindData[0]) { if (!target.mindData[0].some(tNode => tNode.id === node.id && tNode.pid === node.pid && tNode.text === node.text)) { target.mindData[0].push(node); } } return target; };
const sourceFilePath = readlineSync.question('Enter the source file UNC path: ').trim().replace(/^"|"$/g, ''); const targetFilePath = readlineSync.question('Enter the target file UNC path: ').trim().replace(/^"|"$/g, '');
readJSONBlock(sourceFilePath, (err, sourceMindmap) => { if (err) { console.error(err); return; }
readJSONBlock(targetFilePath, (err, targetMindmap) => { if (err) { console.error(err); return; }
const updatedMindmap = updateMindmap(targetMindmap, sourceMindmap);
fs.readFile(targetFilePath, 'utf-8', (err, targetFileContent) => {
if (err) {
console.error(err);
return;
}
const jsonStart = targetFileContent.indexOf('{');
const jsonEnd = targetFileContent.lastIndexOf('}') + 1;
const updatedJSONBlock = JSON.stringify(updatedMindmap, null, 2);
const updatedTargetFileContent = targetFileContent.substring(0, jsonStart) + updatedJSONBlock + targetFileContent.substring(jsonEnd);
fs.writeFile(targetFilePath, updatedTargetFileContent, 'utf-8', (err) => {
if (err) {
console.error(err);
} else {
console.log('Updated mindmap JSON block saved to target.md');
}
});
});
}); });`
v041, a reader to read the json tree, handy and also support unc path.
`const readline = require('readline'); const fs = require('fs'); const yaml = require('js-yaml');
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
rl.question('Enter the UNC path of the file to read: ', (inputPath) => { const filePath = inputPath.trim().replace(/^"|"$/g, '');
fs.readFile(filePath, 'utf-8', (err, data) => { if (err) { console.error(err); rl.close(); return; }
// Extract the YAML front matter
const frontMatterEnd = data.indexOf('---', 4);
const frontMatter = data.substring(4, frontMatterEnd);
console.log('YAML Front Matter:\n');
console.log(frontMatter);
// Extract and parse the JSON block
const jsonStart = data.indexOf('{');
const jsonEnd = data.lastIndexOf('}') + 1;
const jsonBlock = JSON.parse(data.substring(jsonStart, jsonEnd));
console.log('\nParsed JSON Block:\n');
console.log(JSON.stringify(jsonBlock, null, 2));
// Display details about the JSON block
console.log('\nJSON Block Details:');
console.log(`- Number of keys: ${Object.keys(jsonBlock).length}`);
for (const key in jsonBlock) {
console.log(`- Key "${key}" has type ${typeof jsonBlock[key]} and value: ${JSON.stringify(jsonBlock[key])}`);
}
rl.close();
}); });`
hi, previous say the last block for data flow between basic/rich, old, new is how to update a rich map from a rich map. just used gpt to write a .js script, to show proof of concept first, that you can do so.
points:
pls advise and see if author would make it into a ctrlP function. thanks