Skip to content

Commit

Permalink
improve functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
lugenx committed May 3, 2023
1 parent 75360c5 commit 2c6e148
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 34 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
# google-keep-to-logseq
# Keep2Log - Google Keep to Logseq Converter

Keep2Log is a CLI tool that converts Google Keep Takeout files to Logseq journal entries, allowing you to migrate your notes from Google Keep to the Logseq note-taking app.

## Table of Contents

- [Installation](#installation)
- [Usage](#usage)
- [Background](#background)
- [License](#license)

## Installation

1. Download the latest release of Keep2Log for your platform (Windows, Mac, or Linux) from the [Releases](https://github.com/lugenx/keep2log/releases) page.

2. Extract the downloaded archive, if necessary, to obtain the Keep2Log executable.

## Usage

1. Export your Google Keep data using [Google Takeout](https://takeout.google.com/). Select "Google Keep" and download the archive.

2. Extract the Google Keep Takeout archive to a folder.

3. Run the Keep2Log executable. The tool will guide you through the process with messages in the command line. You'll be prompted to provide the path to the extracted Google Keep folder and the output directory for the Logseq journal entries.

4. Import the converted journal entries into Logseq.

## Background

I initially created Keep2Log to migrate my own notes from Google Keep to Logseq. After experiencing the convenience and usefulness of this conversion process, I decided to share the tool on GitHub for others who may be facing similar needs. I hope Keep2Log helps you easily transition your notes from Google Keep to Logseq and enhances your note-taking experience.
19 changes: 7 additions & 12 deletions convertFile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const fs = require("node:fs");

const convertFile = (file) => {
const date = new Date(file.createdTimestampUsec / 1000);
const year = date.getFullYear();
Expand All @@ -16,25 +14,22 @@ const convertFile = (file) => {
hours = hours.toString().padStart(2, "0");
minutes = minutes.toString().padStart(2, "0");

const logseqJournalFilename = `${year}_${month}_${day}.md`;
const mdFileName = `${year}_${month}_${day}.md`;

const title = file.title;
const text = file.textContent;

const content = title
? `\n- **${title.trim()}** (${hours}:${minutes}) \n\t- ${text.replaceAll(
? `\n- **${title.trim()}** (${hours}:${minutes}) \n\t- ${text?.replaceAll(
/\n(.+)/g,
"\n\t- $1"
)}`
: `\n- ${hours}:${minutes} \n\t- ${text.replaceAll(/\n(.+)/g, "\n\t- $1")}`;

fs.appendFile(logseqJournalFilename, content, (err) => {
if (err) {
console.log("Error happened while writing the file");
}
});
: `\n- ${hours}:${minutes} \n\t- ${text?.replaceAll(
/\n(.+)/g,
"\n\t- $1"
)}`;

return;
return { mdFileName, content };
};

module.exports = convertFile;
17 changes: 17 additions & 0 deletions createOrReturnDirectory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const createOrReturnDirectory = (pathToCreate) => {
const fs = require("node:fs");
const path = require("node:path");

const normalizedPath = path.normalize(pathToCreate);

if (fs.existsSync(normalizedPath)) return normalizedPath;

try {
createdPath = fs.mkdirSync(pathToCreate, { recursive: true });
return normalizedPath;
} catch (error) {
console.log("Error in createPath ", error);
}
};

module.exports = createOrReturnDirectory;
81 changes: 60 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,84 @@ const path = require("node:path");
const readline = require("node:readline");
const { stdin: input, stdout: output } = require("node:process");
const convertFile = require("./convertFile.js");
const createOrReturnDirectory = require("./createOrReturnDirectory.js");

const rl = readline.createInterface({ input, output });
const FILE_PATH = "/Users/elgun/desktop";

rl.question(
"\n\x1b[33m Enter the name of the folder that exported from Google Keep?\x1b[0m\n\n > ",
(folderName) => {
// console.log(`Answer is here: ${folderName}`);
let jsonFiles;
// TODO: Below will read directory and create array of json fles

const FIRST_QUESTION =
" \n\x1b[1m\x1b[33mEnter the location of downloaded and unzipped 'Google Keep' Takeout folder?\x1b[0m \n\x1b[33m e.g. /Users/<your username>/desktop/\x1b[0m\n\n >";
const SECOND_QUESTION =
" \n\x1b[1m\x1b[33mEnter location of your 'Journals' folder or press 'ENTER' if you want to create new 'journals' folder in current location\x1b[0m \n\x1b[33m e.g. /Users/<your username>/Documents/<Logseq Graph name>/\x1b[0m\n\n >";

let sourceDirectory;
let destinationDirectory;
let jsonFiles;

const runFirstQuestion = () => {
rl.question(FIRST_QUESTION, (askedFolderLocation) => {
sourceDirectory = path.normalize(`${askedFolderLocation}/Takeout/Keep/`);

if (
!fs.existsSync(sourceDirectory) ||
!fs.statSync(sourceDirectory).isDirectory()
) {
console.log(
"\n\x1b[1m\x1b[31mTakeout folder not found! Please try again!\x1b[0m"
);
return runFirstQuestion();
}

try {
const files = fs.readdirSync(`/${FILE_PATH}/${folderName}/Keep/`);
const files = fs.readdirSync(sourceDirectory);

jsonFiles = files.filter(
(file) => path.extname(file).toLowerCase() === ".json"
);
// console.log("this runs firs - json files", jsonFiles);
runSecondQuestion();
} catch (error) {
console.log("Error getting directory info");
}
});
};

// TODO: Iterate over all json files (jsonFiles) and handle each file and structure data
// console.log("json files ", jsonFiles);
const runSecondQuestion = () => {
rl.question(SECOND_QUESTION, (askedDestinationLocation) => {
destinationDirectory = path.normalize(askedDestinationLocation);

// TODO: Below will read the json file
if (
!fs.existsSync(destinationDirectory) ||
!fs.statSync(destinationDirectory).isDirectory()
) {
console.log(
"\n\x1b[1m\x1b[31mDestination location is not valid! Please try again!\x1b[0m"
);
return runSecondQuestion();
}

let processedFilesCount = 0;
for (let file of jsonFiles) {
try {
const fileContent = fs.readFileSync(
`${FILE_PATH}/${folderName}/keep/${file}`
);
const fileContent = fs.readFileSync(`${sourceDirectory}/${file}`);
const jsonData = JSON.parse(fileContent);
const { mdFileName, content } = convertFile(jsonData);

console.log(convertFile(jsonData));
const pathToAppend = createOrReturnDirectory(
`${destinationDirectory}/journals/`
);

fs.appendFileSync(`${pathToAppend}/${mdFileName}`, content);
processedFilesCount++;
} catch (error) {
console.error(error);
}
}

console.log(
`\n\x1b[92m All files processed. Total converted files: ${processedFilesCount}. \n Please look for newly created 'journals' folder in '${
destinationDirectory === "." ? __dirname : destinationDirectory
}' directory. \x1b[0m\n`
);
rl.close();
}
);
});
};

// console.log("\n\x1b[92m The file has been formatted and saved! \x1b[0m\n");
runFirstQuestion();
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "keep2log",
"version": "1.0.0",
"bin": {
"keep2log": "index.js"
},
"description": "Single executable CLI tool to conver Google Keep notes to Logseq journal entries",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

0 comments on commit 2c6e148

Please sign in to comment.